xref: /openbsd-src/gnu/llvm/lldb/source/Commands/CommandObjectTarget.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1dda28197Spatrick //===-- CommandObjectTarget.cpp -------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "CommandObjectTarget.h"
10061da546Spatrick 
11061da546Spatrick #include "lldb/Core/Debugger.h"
12061da546Spatrick #include "lldb/Core/IOHandler.h"
13061da546Spatrick #include "lldb/Core/Module.h"
14061da546Spatrick #include "lldb/Core/ModuleSpec.h"
15061da546Spatrick #include "lldb/Core/Section.h"
16061da546Spatrick #include "lldb/Core/ValueObjectVariable.h"
17061da546Spatrick #include "lldb/DataFormatters/ValueObjectPrinter.h"
18061da546Spatrick #include "lldb/Host/OptionParser.h"
19061da546Spatrick #include "lldb/Interpreter/CommandInterpreter.h"
20*f6aab3d8Srobert #include "lldb/Interpreter/CommandOptionArgumentTable.h"
21061da546Spatrick #include "lldb/Interpreter/CommandReturnObject.h"
22061da546Spatrick #include "lldb/Interpreter/OptionArgParser.h"
23061da546Spatrick #include "lldb/Interpreter/OptionGroupArchitecture.h"
24061da546Spatrick #include "lldb/Interpreter/OptionGroupBoolean.h"
25061da546Spatrick #include "lldb/Interpreter/OptionGroupFile.h"
26061da546Spatrick #include "lldb/Interpreter/OptionGroupFormat.h"
27be691f3bSpatrick #include "lldb/Interpreter/OptionGroupPlatform.h"
28be691f3bSpatrick #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"
29061da546Spatrick #include "lldb/Interpreter/OptionGroupString.h"
30061da546Spatrick #include "lldb/Interpreter/OptionGroupUInt64.h"
31061da546Spatrick #include "lldb/Interpreter/OptionGroupUUID.h"
32061da546Spatrick #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
33061da546Spatrick #include "lldb/Interpreter/OptionGroupVariable.h"
34061da546Spatrick #include "lldb/Interpreter/Options.h"
35061da546Spatrick #include "lldb/Symbol/CompileUnit.h"
36061da546Spatrick #include "lldb/Symbol/FuncUnwinders.h"
37061da546Spatrick #include "lldb/Symbol/LineTable.h"
38061da546Spatrick #include "lldb/Symbol/LocateSymbolFile.h"
39061da546Spatrick #include "lldb/Symbol/ObjectFile.h"
40061da546Spatrick #include "lldb/Symbol/SymbolFile.h"
41061da546Spatrick #include "lldb/Symbol/UnwindPlan.h"
42061da546Spatrick #include "lldb/Symbol/VariableList.h"
43061da546Spatrick #include "lldb/Target/ABI.h"
44061da546Spatrick #include "lldb/Target/Process.h"
45061da546Spatrick #include "lldb/Target/RegisterContext.h"
46061da546Spatrick #include "lldb/Target/SectionLoadList.h"
47061da546Spatrick #include "lldb/Target/StackFrame.h"
48061da546Spatrick #include "lldb/Target/Thread.h"
49061da546Spatrick #include "lldb/Target/ThreadSpec.h"
50061da546Spatrick #include "lldb/Utility/Args.h"
51*f6aab3d8Srobert #include "lldb/Utility/ConstString.h"
52*f6aab3d8Srobert #include "lldb/Utility/FileSpec.h"
53*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
54061da546Spatrick #include "lldb/Utility/State.h"
55061da546Spatrick #include "lldb/Utility/Timer.h"
56*f6aab3d8Srobert #include "lldb/lldb-enumerations.h"
57*f6aab3d8Srobert #include "lldb/lldb-private-enumerations.h"
58061da546Spatrick 
59*f6aab3d8Srobert #include "clang/CodeGen/ObjectFilePCHContainerOperations.h"
60*f6aab3d8Srobert #include "clang/Frontend/CompilerInstance.h"
61*f6aab3d8Srobert #include "clang/Frontend/CompilerInvocation.h"
62*f6aab3d8Srobert #include "clang/Frontend/FrontendActions.h"
63be691f3bSpatrick #include "llvm/ADT/ScopeExit.h"
64061da546Spatrick #include "llvm/Support/FileSystem.h"
65061da546Spatrick #include "llvm/Support/FormatAdapters.h"
66061da546Spatrick 
67061da546Spatrick 
68061da546Spatrick using namespace lldb;
69061da546Spatrick using namespace lldb_private;
70061da546Spatrick 
DumpTargetInfo(uint32_t target_idx,Target * target,const char * prefix_cstr,bool show_stopped_process_status,Stream & strm)71061da546Spatrick static void DumpTargetInfo(uint32_t target_idx, Target *target,
72061da546Spatrick                            const char *prefix_cstr,
73061da546Spatrick                            bool show_stopped_process_status, Stream &strm) {
74061da546Spatrick   const ArchSpec &target_arch = target->GetArchitecture();
75061da546Spatrick 
76061da546Spatrick   Module *exe_module = target->GetExecutableModulePointer();
77061da546Spatrick   char exe_path[PATH_MAX];
78061da546Spatrick   bool exe_valid = false;
79061da546Spatrick   if (exe_module)
80061da546Spatrick     exe_valid = exe_module->GetFileSpec().GetPath(exe_path, sizeof(exe_path));
81061da546Spatrick 
82061da546Spatrick   if (!exe_valid)
83061da546Spatrick     ::strcpy(exe_path, "<none>");
84061da546Spatrick 
85061da546Spatrick   strm.Printf("%starget #%u: %s", prefix_cstr ? prefix_cstr : "", target_idx,
86061da546Spatrick               exe_path);
87061da546Spatrick 
88061da546Spatrick   uint32_t properties = 0;
89061da546Spatrick   if (target_arch.IsValid()) {
90061da546Spatrick     strm.Printf("%sarch=", properties++ > 0 ? ", " : " ( ");
91061da546Spatrick     target_arch.DumpTriple(strm.AsRawOstream());
92061da546Spatrick     properties++;
93061da546Spatrick   }
94061da546Spatrick   PlatformSP platform_sp(target->GetPlatform());
95061da546Spatrick   if (platform_sp)
96*f6aab3d8Srobert     strm.Format("{0}platform={1}", properties++ > 0 ? ", " : " ( ",
97*f6aab3d8Srobert                 platform_sp->GetName());
98061da546Spatrick 
99061da546Spatrick   ProcessSP process_sp(target->GetProcessSP());
100061da546Spatrick   bool show_process_status = false;
101061da546Spatrick   if (process_sp) {
102061da546Spatrick     lldb::pid_t pid = process_sp->GetID();
103061da546Spatrick     StateType state = process_sp->GetState();
104061da546Spatrick     if (show_stopped_process_status)
105061da546Spatrick       show_process_status = StateIsStoppedState(state, true);
106061da546Spatrick     const char *state_cstr = StateAsCString(state);
107061da546Spatrick     if (pid != LLDB_INVALID_PROCESS_ID)
108061da546Spatrick       strm.Printf("%spid=%" PRIu64, properties++ > 0 ? ", " : " ( ", pid);
109061da546Spatrick     strm.Printf("%sstate=%s", properties++ > 0 ? ", " : " ( ", state_cstr);
110061da546Spatrick   }
111061da546Spatrick   if (properties > 0)
112061da546Spatrick     strm.PutCString(" )\n");
113061da546Spatrick   else
114061da546Spatrick     strm.EOL();
115061da546Spatrick   if (show_process_status) {
116061da546Spatrick     const bool only_threads_with_stop_reason = true;
117061da546Spatrick     const uint32_t start_frame = 0;
118061da546Spatrick     const uint32_t num_frames = 1;
119061da546Spatrick     const uint32_t num_frames_with_source = 1;
120061da546Spatrick     const bool stop_format = false;
121061da546Spatrick     process_sp->GetStatus(strm);
122061da546Spatrick     process_sp->GetThreadStatus(strm, only_threads_with_stop_reason,
123061da546Spatrick                                 start_frame, num_frames, num_frames_with_source,
124061da546Spatrick                                 stop_format);
125061da546Spatrick   }
126061da546Spatrick }
127061da546Spatrick 
DumpTargetList(TargetList & target_list,bool show_stopped_process_status,Stream & strm)128061da546Spatrick static uint32_t DumpTargetList(TargetList &target_list,
129061da546Spatrick                                bool show_stopped_process_status, Stream &strm) {
130061da546Spatrick   const uint32_t num_targets = target_list.GetNumTargets();
131061da546Spatrick   if (num_targets) {
132061da546Spatrick     TargetSP selected_target_sp(target_list.GetSelectedTarget());
133061da546Spatrick     strm.PutCString("Current targets:\n");
134061da546Spatrick     for (uint32_t i = 0; i < num_targets; ++i) {
135061da546Spatrick       TargetSP target_sp(target_list.GetTargetAtIndex(i));
136061da546Spatrick       if (target_sp) {
137061da546Spatrick         bool is_selected = target_sp.get() == selected_target_sp.get();
138061da546Spatrick         DumpTargetInfo(i, target_sp.get(), is_selected ? "* " : "  ",
139061da546Spatrick                        show_stopped_process_status, strm);
140061da546Spatrick       }
141061da546Spatrick     }
142061da546Spatrick   }
143061da546Spatrick   return num_targets;
144061da546Spatrick }
145061da546Spatrick 
146061da546Spatrick #define LLDB_OPTIONS_target_dependents
147061da546Spatrick #include "CommandOptions.inc"
148061da546Spatrick 
149061da546Spatrick class OptionGroupDependents : public OptionGroup {
150061da546Spatrick public:
151be691f3bSpatrick   OptionGroupDependents() = default;
152061da546Spatrick 
153be691f3bSpatrick   ~OptionGroupDependents() override = default;
154061da546Spatrick 
GetDefinitions()155061da546Spatrick   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
156*f6aab3d8Srobert     return llvm::ArrayRef(g_target_dependents_options);
157061da546Spatrick   }
158061da546Spatrick 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_value,ExecutionContext * execution_context)159061da546Spatrick   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
160061da546Spatrick                         ExecutionContext *execution_context) override {
161061da546Spatrick     Status error;
162061da546Spatrick 
163061da546Spatrick     // For compatibility no value means don't load dependents.
164061da546Spatrick     if (option_value.empty()) {
165061da546Spatrick       m_load_dependent_files = eLoadDependentsNo;
166061da546Spatrick       return error;
167061da546Spatrick     }
168061da546Spatrick 
169061da546Spatrick     const char short_option =
170061da546Spatrick         g_target_dependents_options[option_idx].short_option;
171061da546Spatrick     if (short_option == 'd') {
172061da546Spatrick       LoadDependentFiles tmp_load_dependents;
173061da546Spatrick       tmp_load_dependents = (LoadDependentFiles)OptionArgParser::ToOptionEnum(
174061da546Spatrick           option_value, g_target_dependents_options[option_idx].enum_values, 0,
175061da546Spatrick           error);
176061da546Spatrick       if (error.Success())
177061da546Spatrick         m_load_dependent_files = tmp_load_dependents;
178061da546Spatrick     } else {
179061da546Spatrick       error.SetErrorStringWithFormat("unrecognized short option '%c'",
180061da546Spatrick                                      short_option);
181061da546Spatrick     }
182061da546Spatrick 
183061da546Spatrick     return error;
184061da546Spatrick   }
185061da546Spatrick 
186061da546Spatrick   Status SetOptionValue(uint32_t, const char *, ExecutionContext *) = delete;
187061da546Spatrick 
OptionParsingStarting(ExecutionContext * execution_context)188061da546Spatrick   void OptionParsingStarting(ExecutionContext *execution_context) override {
189061da546Spatrick     m_load_dependent_files = eLoadDependentsDefault;
190061da546Spatrick   }
191061da546Spatrick 
192061da546Spatrick   LoadDependentFiles m_load_dependent_files;
193061da546Spatrick 
194061da546Spatrick private:
195dda28197Spatrick   OptionGroupDependents(const OptionGroupDependents &) = delete;
196dda28197Spatrick   const OptionGroupDependents &
197dda28197Spatrick   operator=(const OptionGroupDependents &) = delete;
198061da546Spatrick };
199061da546Spatrick 
200061da546Spatrick #pragma mark CommandObjectTargetCreate
201061da546Spatrick 
202061da546Spatrick class CommandObjectTargetCreate : public CommandObjectParsed {
203061da546Spatrick public:
CommandObjectTargetCreate(CommandInterpreter & interpreter)204061da546Spatrick   CommandObjectTargetCreate(CommandInterpreter &interpreter)
205061da546Spatrick       : CommandObjectParsed(
206061da546Spatrick             interpreter, "target create",
207061da546Spatrick             "Create a target using the argument as the main executable.",
208061da546Spatrick             nullptr),
209be691f3bSpatrick         m_platform_options(true), // Include the --platform option.
210061da546Spatrick         m_core_file(LLDB_OPT_SET_1, false, "core", 'c', 0, eArgTypeFilename,
211061da546Spatrick                     "Fullpath to a core file to use for this target."),
212061da546Spatrick         m_symbol_file(LLDB_OPT_SET_1, false, "symfile", 's', 0,
213061da546Spatrick                       eArgTypeFilename,
214061da546Spatrick                       "Fullpath to a stand alone debug "
215061da546Spatrick                       "symbols file for when debug symbols "
216061da546Spatrick                       "are not in the executable."),
217061da546Spatrick         m_remote_file(
218061da546Spatrick             LLDB_OPT_SET_1, false, "remote-file", 'r', 0, eArgTypeFilename,
219*f6aab3d8Srobert             "Fullpath to the file on the remote host if debugging remotely.") {
220061da546Spatrick     CommandArgumentEntry arg;
221061da546Spatrick     CommandArgumentData file_arg;
222061da546Spatrick 
223061da546Spatrick     // Define the first (and only) variant of this arg.
224061da546Spatrick     file_arg.arg_type = eArgTypeFilename;
225061da546Spatrick     file_arg.arg_repetition = eArgRepeatPlain;
226061da546Spatrick 
227061da546Spatrick     // There is only one variant this argument could be; put it into the
228061da546Spatrick     // argument entry.
229061da546Spatrick     arg.push_back(file_arg);
230061da546Spatrick 
231061da546Spatrick     // Push the data for the first argument into the m_arguments vector.
232061da546Spatrick     m_arguments.push_back(arg);
233061da546Spatrick 
234061da546Spatrick     m_option_group.Append(&m_arch_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
235be691f3bSpatrick     m_option_group.Append(&m_platform_options, LLDB_OPT_SET_ALL, 1);
236061da546Spatrick     m_option_group.Append(&m_core_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
237061da546Spatrick     m_option_group.Append(&m_symbol_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
238061da546Spatrick     m_option_group.Append(&m_remote_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
239061da546Spatrick     m_option_group.Append(&m_add_dependents, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
240061da546Spatrick     m_option_group.Finalize();
241061da546Spatrick   }
242061da546Spatrick 
243061da546Spatrick   ~CommandObjectTargetCreate() override = default;
244061da546Spatrick 
GetOptions()245061da546Spatrick   Options *GetOptions() override { return &m_option_group; }
246061da546Spatrick 
247061da546Spatrick   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)248061da546Spatrick   HandleArgumentCompletion(CompletionRequest &request,
249061da546Spatrick                            OptionElementVector &opt_element_vector) override {
250061da546Spatrick     CommandCompletions::InvokeCommonCompletionCallbacks(
251061da546Spatrick         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
252061da546Spatrick         request, nullptr);
253061da546Spatrick   }
254061da546Spatrick 
255061da546Spatrick protected:
DoExecute(Args & command,CommandReturnObject & result)256061da546Spatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
257061da546Spatrick     const size_t argc = command.GetArgumentCount();
258061da546Spatrick     FileSpec core_file(m_core_file.GetOptionValue().GetCurrentValue());
259061da546Spatrick     FileSpec remote_file(m_remote_file.GetOptionValue().GetCurrentValue());
260061da546Spatrick 
261061da546Spatrick     if (core_file) {
262dda28197Spatrick       auto file = FileSystem::Instance().Open(
263*f6aab3d8Srobert           core_file, lldb_private::File::eOpenOptionReadOnly);
264dda28197Spatrick 
265dda28197Spatrick       if (!file) {
266dda28197Spatrick         result.AppendErrorWithFormatv("Cannot open '{0}': {1}.",
267dda28197Spatrick                                       core_file.GetPath(),
268dda28197Spatrick                                       llvm::toString(file.takeError()));
269061da546Spatrick         return false;
270061da546Spatrick       }
271061da546Spatrick     }
272061da546Spatrick 
273061da546Spatrick     if (argc == 1 || core_file || remote_file) {
274061da546Spatrick       FileSpec symfile(m_symbol_file.GetOptionValue().GetCurrentValue());
275061da546Spatrick       if (symfile) {
276dda28197Spatrick         auto file = FileSystem::Instance().Open(
277*f6aab3d8Srobert             symfile, lldb_private::File::eOpenOptionReadOnly);
278dda28197Spatrick 
279dda28197Spatrick         if (!file) {
280dda28197Spatrick           result.AppendErrorWithFormatv("Cannot open '{0}': {1}.",
281dda28197Spatrick                                         symfile.GetPath(),
282dda28197Spatrick                                         llvm::toString(file.takeError()));
283061da546Spatrick           return false;
284061da546Spatrick         }
285061da546Spatrick       }
286061da546Spatrick 
287061da546Spatrick       const char *file_path = command.GetArgumentAtIndex(0);
288be691f3bSpatrick       LLDB_SCOPED_TIMERF("(lldb) target create '%s'", file_path);
289061da546Spatrick 
290061da546Spatrick       bool must_set_platform_path = false;
291061da546Spatrick 
292061da546Spatrick       Debugger &debugger = GetDebugger();
293061da546Spatrick 
294061da546Spatrick       TargetSP target_sp;
295061da546Spatrick       llvm::StringRef arch_cstr = m_arch_option.GetArchitectureName();
296061da546Spatrick       Status error(debugger.GetTargetList().CreateTarget(
297061da546Spatrick           debugger, file_path, arch_cstr,
298be691f3bSpatrick           m_add_dependents.m_load_dependent_files, &m_platform_options,
299be691f3bSpatrick           target_sp));
300061da546Spatrick 
301be691f3bSpatrick       if (!target_sp) {
302be691f3bSpatrick         result.AppendError(error.AsCString());
303be691f3bSpatrick         return false;
304be691f3bSpatrick       }
305be691f3bSpatrick 
306be691f3bSpatrick       auto on_error = llvm::make_scope_exit(
307be691f3bSpatrick           [&target_list = debugger.GetTargetList(), &target_sp]() {
308be691f3bSpatrick             target_list.DeleteTarget(target_sp);
309be691f3bSpatrick           });
310be691f3bSpatrick 
311061da546Spatrick       // Only get the platform after we create the target because we might
312061da546Spatrick       // have switched platforms depending on what the arguments were to
313061da546Spatrick       // CreateTarget() we can't rely on the selected platform.
314061da546Spatrick 
315061da546Spatrick       PlatformSP platform_sp = target_sp->GetPlatform();
316061da546Spatrick 
317*f6aab3d8Srobert       FileSpec file_spec;
318*f6aab3d8Srobert       if (file_path) {
319*f6aab3d8Srobert         file_spec.SetFile(file_path, FileSpec::Style::native);
320*f6aab3d8Srobert         FileSystem::Instance().Resolve(file_spec);
321*f6aab3d8Srobert 
322*f6aab3d8Srobert         // Try to resolve the exe based on PATH and/or platform-specific
323*f6aab3d8Srobert         // suffixes, but only if using the host platform.
324*f6aab3d8Srobert         if (platform_sp && platform_sp->IsHost() &&
325*f6aab3d8Srobert             !FileSystem::Instance().Exists(file_spec))
326*f6aab3d8Srobert           FileSystem::Instance().ResolveExecutableLocation(file_spec);
327*f6aab3d8Srobert       }
328*f6aab3d8Srobert 
329061da546Spatrick       if (remote_file) {
330061da546Spatrick         if (platform_sp) {
331061da546Spatrick           // I have a remote file.. two possible cases
332061da546Spatrick           if (file_spec && FileSystem::Instance().Exists(file_spec)) {
333061da546Spatrick             // if the remote file does not exist, push it there
334061da546Spatrick             if (!platform_sp->GetFileExists(remote_file)) {
335061da546Spatrick               Status err = platform_sp->PutFile(file_spec, remote_file);
336061da546Spatrick               if (err.Fail()) {
337061da546Spatrick                 result.AppendError(err.AsCString());
338061da546Spatrick                 return false;
339061da546Spatrick               }
340061da546Spatrick             }
341061da546Spatrick           } else {
342061da546Spatrick             // there is no local file and we need one
343061da546Spatrick             // in order to make the remote ---> local transfer we need a
344061da546Spatrick             // platform
345061da546Spatrick             // TODO: if the user has passed in a --platform argument, use it
346061da546Spatrick             // to fetch the right platform
347061da546Spatrick             if (file_path) {
348061da546Spatrick               // copy the remote file to the local file
349061da546Spatrick               Status err = platform_sp->GetFile(remote_file, file_spec);
350061da546Spatrick               if (err.Fail()) {
351061da546Spatrick                 result.AppendError(err.AsCString());
352061da546Spatrick                 return false;
353061da546Spatrick               }
354061da546Spatrick             } else {
355*f6aab3d8Srobert               // If the remote file exists, we can debug reading that out of
356*f6aab3d8Srobert               // memory.  If the platform is already connected to an lldb-server
357*f6aab3d8Srobert               // then we can at least check the file exists remotely.  Otherwise
358*f6aab3d8Srobert               // we'll just have to trust that it will be there when we do
359*f6aab3d8Srobert               // process connect.
360*f6aab3d8Srobert               // I don't do this for the host platform because it seems odd to
361*f6aab3d8Srobert               // support supplying a remote file but no local file for a local
362*f6aab3d8Srobert               // debug session.
363*f6aab3d8Srobert               if (platform_sp->IsHost()) {
364*f6aab3d8Srobert                 result.AppendError("Supply a local file, not a remote file, "
365*f6aab3d8Srobert                                    "when debugging on the host.");
366*f6aab3d8Srobert                 return false;
367*f6aab3d8Srobert               }
368*f6aab3d8Srobert               if (platform_sp->IsConnected() && !platform_sp->GetFileExists(remote_file)) {
369061da546Spatrick                 result.AppendError("remote --> local transfer without local "
370061da546Spatrick                                  "path is not implemented yet");
371061da546Spatrick                 return false;
372061da546Spatrick               }
373*f6aab3d8Srobert               // Since there's only a remote file, we need to set the executable
374*f6aab3d8Srobert               // file spec to the remote one.
375*f6aab3d8Srobert               ProcessLaunchInfo launch_info = target_sp->GetProcessLaunchInfo();
376*f6aab3d8Srobert               launch_info.SetExecutableFile(FileSpec(remote_file), true);
377*f6aab3d8Srobert               target_sp->SetProcessLaunchInfo(launch_info);
378*f6aab3d8Srobert             }
379061da546Spatrick           }
380061da546Spatrick         } else {
381061da546Spatrick           result.AppendError("no platform found for target");
382061da546Spatrick           return false;
383061da546Spatrick         }
384061da546Spatrick       }
385061da546Spatrick 
386061da546Spatrick       if (symfile || remote_file) {
387061da546Spatrick         ModuleSP module_sp(target_sp->GetExecutableModule());
388061da546Spatrick         if (module_sp) {
389061da546Spatrick           if (symfile)
390061da546Spatrick             module_sp->SetSymbolFileFileSpec(symfile);
391061da546Spatrick           if (remote_file) {
392061da546Spatrick             std::string remote_path = remote_file.GetPath();
393061da546Spatrick             target_sp->SetArg0(remote_path.c_str());
394061da546Spatrick             module_sp->SetPlatformFileSpec(remote_file);
395061da546Spatrick           }
396061da546Spatrick         }
397061da546Spatrick       }
398061da546Spatrick 
399061da546Spatrick       if (must_set_platform_path) {
400061da546Spatrick         ModuleSpec main_module_spec(file_spec);
401061da546Spatrick         ModuleSP module_sp =
402061da546Spatrick             target_sp->GetOrCreateModule(main_module_spec, true /* notify */);
403061da546Spatrick         if (module_sp)
404061da546Spatrick           module_sp->SetPlatformFileSpec(remote_file);
405061da546Spatrick       }
406dda28197Spatrick 
407061da546Spatrick       if (core_file) {
408061da546Spatrick         FileSpec core_file_dir;
409*f6aab3d8Srobert         core_file_dir.SetDirectory(core_file.GetDirectory());
410061da546Spatrick         target_sp->AppendExecutableSearchPaths(core_file_dir);
411061da546Spatrick 
412061da546Spatrick         ProcessSP process_sp(target_sp->CreateProcess(
413be691f3bSpatrick             GetDebugger().GetListener(), llvm::StringRef(), &core_file, false));
414061da546Spatrick 
415061da546Spatrick         if (process_sp) {
416061da546Spatrick           // Seems weird that we Launch a core file, but that is what we
417061da546Spatrick           // do!
418061da546Spatrick           error = process_sp->LoadCore();
419061da546Spatrick 
420061da546Spatrick           if (error.Fail()) {
421061da546Spatrick             result.AppendError(
422061da546Spatrick                 error.AsCString("can't find plug-in for core file"));
423061da546Spatrick             return false;
424061da546Spatrick           } else {
425be691f3bSpatrick             result.AppendMessageWithFormatv(
426be691f3bSpatrick                 "Core file '{0}' ({1}) was loaded.\n", core_file.GetPath(),
427061da546Spatrick                 target_sp->GetArchitecture().GetArchitectureName());
428061da546Spatrick             result.SetStatus(eReturnStatusSuccessFinishNoResult);
429be691f3bSpatrick             on_error.release();
430061da546Spatrick           }
431061da546Spatrick         } else {
432dda28197Spatrick           result.AppendErrorWithFormatv(
433dda28197Spatrick               "Unable to find process plug-in for core file '{0}'\n",
434dda28197Spatrick               core_file.GetPath());
435061da546Spatrick         }
436061da546Spatrick       } else {
437061da546Spatrick         result.AppendMessageWithFormat(
438061da546Spatrick             "Current executable set to '%s' (%s).\n",
439061da546Spatrick             file_spec.GetPath().c_str(),
440061da546Spatrick             target_sp->GetArchitecture().GetArchitectureName());
441061da546Spatrick         result.SetStatus(eReturnStatusSuccessFinishNoResult);
442be691f3bSpatrick         on_error.release();
443061da546Spatrick       }
444061da546Spatrick     } else {
445061da546Spatrick       result.AppendErrorWithFormat("'%s' takes exactly one executable path "
446061da546Spatrick                                    "argument, or use the --core option.\n",
447061da546Spatrick                                    m_cmd_name.c_str());
448061da546Spatrick     }
449be691f3bSpatrick 
450061da546Spatrick     return result.Succeeded();
451061da546Spatrick   }
452061da546Spatrick 
453061da546Spatrick private:
454061da546Spatrick   OptionGroupOptions m_option_group;
455061da546Spatrick   OptionGroupArchitecture m_arch_option;
456be691f3bSpatrick   OptionGroupPlatform m_platform_options;
457061da546Spatrick   OptionGroupFile m_core_file;
458061da546Spatrick   OptionGroupFile m_symbol_file;
459061da546Spatrick   OptionGroupFile m_remote_file;
460061da546Spatrick   OptionGroupDependents m_add_dependents;
461061da546Spatrick };
462061da546Spatrick 
463061da546Spatrick #pragma mark CommandObjectTargetList
464061da546Spatrick 
465061da546Spatrick class CommandObjectTargetList : public CommandObjectParsed {
466061da546Spatrick public:
CommandObjectTargetList(CommandInterpreter & interpreter)467061da546Spatrick   CommandObjectTargetList(CommandInterpreter &interpreter)
468061da546Spatrick       : CommandObjectParsed(
469061da546Spatrick             interpreter, "target list",
470061da546Spatrick             "List all current targets in the current debug session.", nullptr) {
471061da546Spatrick   }
472061da546Spatrick 
473061da546Spatrick   ~CommandObjectTargetList() override = default;
474061da546Spatrick 
475061da546Spatrick protected:
DoExecute(Args & args,CommandReturnObject & result)476061da546Spatrick   bool DoExecute(Args &args, CommandReturnObject &result) override {
477061da546Spatrick     Stream &strm = result.GetOutputStream();
478061da546Spatrick 
479061da546Spatrick     bool show_stopped_process_status = false;
480061da546Spatrick     if (DumpTargetList(GetDebugger().GetTargetList(),
481061da546Spatrick                        show_stopped_process_status, strm) == 0) {
482061da546Spatrick       strm.PutCString("No targets.\n");
483061da546Spatrick     }
484061da546Spatrick     result.SetStatus(eReturnStatusSuccessFinishResult);
485061da546Spatrick     return result.Succeeded();
486061da546Spatrick   }
487061da546Spatrick };
488061da546Spatrick 
489061da546Spatrick #pragma mark CommandObjectTargetSelect
490061da546Spatrick 
491061da546Spatrick class CommandObjectTargetSelect : public CommandObjectParsed {
492061da546Spatrick public:
CommandObjectTargetSelect(CommandInterpreter & interpreter)493061da546Spatrick   CommandObjectTargetSelect(CommandInterpreter &interpreter)
494061da546Spatrick       : CommandObjectParsed(
495061da546Spatrick             interpreter, "target select",
496061da546Spatrick             "Select a target as the current target by target index.", nullptr) {
497*f6aab3d8Srobert     CommandArgumentData target_arg{eArgTypeTargetID, eArgRepeatPlain};
498*f6aab3d8Srobert     m_arguments.push_back({target_arg});
499061da546Spatrick   }
500061da546Spatrick 
501061da546Spatrick   ~CommandObjectTargetSelect() override = default;
502061da546Spatrick 
503061da546Spatrick protected:
DoExecute(Args & args,CommandReturnObject & result)504061da546Spatrick   bool DoExecute(Args &args, CommandReturnObject &result) override {
505061da546Spatrick     if (args.GetArgumentCount() == 1) {
506061da546Spatrick       const char *target_idx_arg = args.GetArgumentAtIndex(0);
507dda28197Spatrick       uint32_t target_idx;
508dda28197Spatrick       if (llvm::to_integer(target_idx_arg, target_idx)) {
509061da546Spatrick         TargetList &target_list = GetDebugger().GetTargetList();
510061da546Spatrick         const uint32_t num_targets = target_list.GetNumTargets();
511061da546Spatrick         if (target_idx < num_targets) {
512be691f3bSpatrick           target_list.SetSelectedTarget(target_idx);
513061da546Spatrick           Stream &strm = result.GetOutputStream();
514061da546Spatrick           bool show_stopped_process_status = false;
515061da546Spatrick           DumpTargetList(target_list, show_stopped_process_status, strm);
516061da546Spatrick           result.SetStatus(eReturnStatusSuccessFinishResult);
517061da546Spatrick         } else {
518061da546Spatrick           if (num_targets > 0) {
519061da546Spatrick             result.AppendErrorWithFormat(
520061da546Spatrick                 "index %u is out of range, valid target indexes are 0 - %u\n",
521061da546Spatrick                 target_idx, num_targets - 1);
522061da546Spatrick           } else {
523061da546Spatrick             result.AppendErrorWithFormat(
524061da546Spatrick                 "index %u is out of range since there are no active targets\n",
525061da546Spatrick                 target_idx);
526061da546Spatrick           }
527061da546Spatrick         }
528061da546Spatrick       } else {
529061da546Spatrick         result.AppendErrorWithFormat("invalid index string value '%s'\n",
530061da546Spatrick                                      target_idx_arg);
531061da546Spatrick       }
532061da546Spatrick     } else {
533061da546Spatrick       result.AppendError(
534061da546Spatrick           "'target select' takes a single argument: a target index\n");
535061da546Spatrick     }
536061da546Spatrick     return result.Succeeded();
537061da546Spatrick   }
538061da546Spatrick };
539061da546Spatrick 
540dda28197Spatrick #pragma mark CommandObjectTargetDelete
541061da546Spatrick 
542061da546Spatrick class CommandObjectTargetDelete : public CommandObjectParsed {
543061da546Spatrick public:
CommandObjectTargetDelete(CommandInterpreter & interpreter)544061da546Spatrick   CommandObjectTargetDelete(CommandInterpreter &interpreter)
545061da546Spatrick       : CommandObjectParsed(interpreter, "target delete",
546061da546Spatrick                             "Delete one or more targets by target index.",
547061da546Spatrick                             nullptr),
548*f6aab3d8Srobert         m_all_option(LLDB_OPT_SET_1, false, "all", 'a', "Delete all targets.",
549*f6aab3d8Srobert                      false, true),
550061da546Spatrick         m_cleanup_option(
551061da546Spatrick             LLDB_OPT_SET_1, false, "clean", 'c',
552061da546Spatrick             "Perform extra cleanup to minimize memory consumption after "
553061da546Spatrick             "deleting the target.  "
554061da546Spatrick             "By default, LLDB will keep in memory any modules previously "
555061da546Spatrick             "loaded by the target as well "
556061da546Spatrick             "as all of its debug info.  Specifying --clean will unload all of "
557061da546Spatrick             "these shared modules and "
558061da546Spatrick             "cause them to be reparsed again the next time the target is run",
559061da546Spatrick             false, true) {
560061da546Spatrick     m_option_group.Append(&m_all_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
561061da546Spatrick     m_option_group.Append(&m_cleanup_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
562061da546Spatrick     m_option_group.Finalize();
563*f6aab3d8Srobert     CommandArgumentData target_arg{eArgTypeTargetID, eArgRepeatStar};
564*f6aab3d8Srobert     m_arguments.push_back({target_arg});
565061da546Spatrick   }
566061da546Spatrick 
567061da546Spatrick   ~CommandObjectTargetDelete() override = default;
568061da546Spatrick 
GetOptions()569061da546Spatrick   Options *GetOptions() override { return &m_option_group; }
570061da546Spatrick 
571061da546Spatrick protected:
DoExecute(Args & args,CommandReturnObject & result)572061da546Spatrick   bool DoExecute(Args &args, CommandReturnObject &result) override {
573061da546Spatrick     const size_t argc = args.GetArgumentCount();
574061da546Spatrick     std::vector<TargetSP> delete_target_list;
575061da546Spatrick     TargetList &target_list = GetDebugger().GetTargetList();
576061da546Spatrick     TargetSP target_sp;
577061da546Spatrick 
578061da546Spatrick     if (m_all_option.GetOptionValue()) {
579061da546Spatrick       for (int i = 0; i < target_list.GetNumTargets(); ++i)
580061da546Spatrick         delete_target_list.push_back(target_list.GetTargetAtIndex(i));
581061da546Spatrick     } else if (argc > 0) {
582061da546Spatrick       const uint32_t num_targets = target_list.GetNumTargets();
583061da546Spatrick       // Bail out if don't have any targets.
584061da546Spatrick       if (num_targets == 0) {
585061da546Spatrick         result.AppendError("no targets to delete");
586061da546Spatrick         return false;
587061da546Spatrick       }
588061da546Spatrick 
589061da546Spatrick       for (auto &entry : args.entries()) {
590061da546Spatrick         uint32_t target_idx;
591061da546Spatrick         if (entry.ref().getAsInteger(0, target_idx)) {
592061da546Spatrick           result.AppendErrorWithFormat("invalid target index '%s'\n",
593061da546Spatrick                                        entry.c_str());
594061da546Spatrick           return false;
595061da546Spatrick         }
596061da546Spatrick         if (target_idx < num_targets) {
597061da546Spatrick           target_sp = target_list.GetTargetAtIndex(target_idx);
598061da546Spatrick           if (target_sp) {
599061da546Spatrick             delete_target_list.push_back(target_sp);
600061da546Spatrick             continue;
601061da546Spatrick           }
602061da546Spatrick         }
603061da546Spatrick         if (num_targets > 1)
604061da546Spatrick           result.AppendErrorWithFormat("target index %u is out of range, valid "
605061da546Spatrick                                        "target indexes are 0 - %u\n",
606061da546Spatrick                                        target_idx, num_targets - 1);
607061da546Spatrick         else
608061da546Spatrick           result.AppendErrorWithFormat(
609061da546Spatrick               "target index %u is out of range, the only valid index is 0\n",
610061da546Spatrick               target_idx);
611061da546Spatrick 
612061da546Spatrick         return false;
613061da546Spatrick       }
614061da546Spatrick     } else {
615061da546Spatrick       target_sp = target_list.GetSelectedTarget();
616061da546Spatrick       if (!target_sp) {
617061da546Spatrick         result.AppendErrorWithFormat("no target is currently selected\n");
618061da546Spatrick         return false;
619061da546Spatrick       }
620061da546Spatrick       delete_target_list.push_back(target_sp);
621061da546Spatrick     }
622061da546Spatrick 
623061da546Spatrick     const size_t num_targets_to_delete = delete_target_list.size();
624061da546Spatrick     for (size_t idx = 0; idx < num_targets_to_delete; ++idx) {
625061da546Spatrick       target_sp = delete_target_list[idx];
626061da546Spatrick       target_list.DeleteTarget(target_sp);
627061da546Spatrick       target_sp->Destroy();
628061da546Spatrick     }
629061da546Spatrick     // If "--clean" was specified, prune any orphaned shared modules from the
630061da546Spatrick     // global shared module list
631061da546Spatrick     if (m_cleanup_option.GetOptionValue()) {
632061da546Spatrick       const bool mandatory = true;
633061da546Spatrick       ModuleList::RemoveOrphanSharedModules(mandatory);
634061da546Spatrick     }
635061da546Spatrick     result.GetOutputStream().Printf("%u targets deleted.\n",
636061da546Spatrick                                     (uint32_t)num_targets_to_delete);
637061da546Spatrick     result.SetStatus(eReturnStatusSuccessFinishResult);
638061da546Spatrick 
639061da546Spatrick     return true;
640061da546Spatrick   }
641061da546Spatrick 
642061da546Spatrick   OptionGroupOptions m_option_group;
643061da546Spatrick   OptionGroupBoolean m_all_option;
644061da546Spatrick   OptionGroupBoolean m_cleanup_option;
645061da546Spatrick };
646061da546Spatrick 
647dda28197Spatrick class CommandObjectTargetShowLaunchEnvironment : public CommandObjectParsed {
648dda28197Spatrick public:
CommandObjectTargetShowLaunchEnvironment(CommandInterpreter & interpreter)649dda28197Spatrick   CommandObjectTargetShowLaunchEnvironment(CommandInterpreter &interpreter)
650dda28197Spatrick       : CommandObjectParsed(
651dda28197Spatrick             interpreter, "target show-launch-environment",
652dda28197Spatrick             "Shows the environment being passed to the process when launched, "
653dda28197Spatrick             "taking info account 3 settings: target.env-vars, "
654dda28197Spatrick             "target.inherit-env and target.unset-env-vars.",
655dda28197Spatrick             nullptr, eCommandRequiresTarget) {}
656dda28197Spatrick 
657dda28197Spatrick   ~CommandObjectTargetShowLaunchEnvironment() override = default;
658dda28197Spatrick 
659dda28197Spatrick protected:
DoExecute(Args & args,CommandReturnObject & result)660dda28197Spatrick   bool DoExecute(Args &args, CommandReturnObject &result) override {
661dda28197Spatrick     Target *target = m_exe_ctx.GetTargetPtr();
662dda28197Spatrick     Environment env = target->GetEnvironment();
663dda28197Spatrick 
664dda28197Spatrick     std::vector<Environment::value_type *> env_vector;
665dda28197Spatrick     env_vector.reserve(env.size());
666dda28197Spatrick     for (auto &KV : env)
667dda28197Spatrick       env_vector.push_back(&KV);
668dda28197Spatrick     std::sort(env_vector.begin(), env_vector.end(),
669dda28197Spatrick               [](Environment::value_type *a, Environment::value_type *b) {
670dda28197Spatrick                 return a->first() < b->first();
671dda28197Spatrick               });
672dda28197Spatrick 
673dda28197Spatrick     auto &strm = result.GetOutputStream();
674dda28197Spatrick     for (auto &KV : env_vector)
675dda28197Spatrick       strm.Format("{0}={1}\n", KV->first(), KV->second);
676dda28197Spatrick 
677dda28197Spatrick     result.SetStatus(eReturnStatusSuccessFinishResult);
678dda28197Spatrick     return result.Succeeded();
679dda28197Spatrick   }
680dda28197Spatrick };
681dda28197Spatrick 
682061da546Spatrick #pragma mark CommandObjectTargetVariable
683061da546Spatrick 
684061da546Spatrick class CommandObjectTargetVariable : public CommandObjectParsed {
685061da546Spatrick   static const uint32_t SHORT_OPTION_FILE = 0x66696c65; // 'file'
686061da546Spatrick   static const uint32_t SHORT_OPTION_SHLB = 0x73686c62; // 'shlb'
687061da546Spatrick 
688061da546Spatrick public:
CommandObjectTargetVariable(CommandInterpreter & interpreter)689061da546Spatrick   CommandObjectTargetVariable(CommandInterpreter &interpreter)
690061da546Spatrick       : CommandObjectParsed(interpreter, "target variable",
691061da546Spatrick                             "Read global variables for the current target, "
692061da546Spatrick                             "before or while running a process.",
693061da546Spatrick                             nullptr, eCommandRequiresTarget),
694061da546Spatrick         m_option_variable(false), // Don't include frame options
695061da546Spatrick         m_option_format(eFormatDefault),
696061da546Spatrick         m_option_compile_units(LLDB_OPT_SET_1, false, "file", SHORT_OPTION_FILE,
697061da546Spatrick                                0, eArgTypeFilename,
698061da546Spatrick                                "A basename or fullpath to a file that contains "
699061da546Spatrick                                "global variables. This option can be "
700061da546Spatrick                                "specified multiple times."),
701061da546Spatrick         m_option_shared_libraries(
702061da546Spatrick             LLDB_OPT_SET_1, false, "shlib", SHORT_OPTION_SHLB, 0,
703061da546Spatrick             eArgTypeFilename,
704061da546Spatrick             "A basename or fullpath to a shared library to use in the search "
705061da546Spatrick             "for global "
706*f6aab3d8Srobert             "variables. This option can be specified multiple times.") {
707061da546Spatrick     CommandArgumentEntry arg;
708061da546Spatrick     CommandArgumentData var_name_arg;
709061da546Spatrick 
710061da546Spatrick     // Define the first (and only) variant of this arg.
711061da546Spatrick     var_name_arg.arg_type = eArgTypeVarName;
712061da546Spatrick     var_name_arg.arg_repetition = eArgRepeatPlus;
713061da546Spatrick 
714061da546Spatrick     // There is only one variant this argument could be; put it into the
715061da546Spatrick     // argument entry.
716061da546Spatrick     arg.push_back(var_name_arg);
717061da546Spatrick 
718061da546Spatrick     // Push the data for the first argument into the m_arguments vector.
719061da546Spatrick     m_arguments.push_back(arg);
720061da546Spatrick 
721061da546Spatrick     m_option_group.Append(&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
722061da546Spatrick     m_option_group.Append(&m_option_variable, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
723061da546Spatrick     m_option_group.Append(&m_option_format,
724061da546Spatrick                           OptionGroupFormat::OPTION_GROUP_FORMAT |
725061da546Spatrick                               OptionGroupFormat::OPTION_GROUP_GDB_FMT,
726061da546Spatrick                           LLDB_OPT_SET_1);
727061da546Spatrick     m_option_group.Append(&m_option_compile_units, LLDB_OPT_SET_ALL,
728061da546Spatrick                           LLDB_OPT_SET_1);
729061da546Spatrick     m_option_group.Append(&m_option_shared_libraries, LLDB_OPT_SET_ALL,
730061da546Spatrick                           LLDB_OPT_SET_1);
731061da546Spatrick     m_option_group.Finalize();
732061da546Spatrick   }
733061da546Spatrick 
734061da546Spatrick   ~CommandObjectTargetVariable() override = default;
735061da546Spatrick 
DumpValueObject(Stream & s,VariableSP & var_sp,ValueObjectSP & valobj_sp,const char * root_name)736061da546Spatrick   void DumpValueObject(Stream &s, VariableSP &var_sp, ValueObjectSP &valobj_sp,
737061da546Spatrick                        const char *root_name) {
738061da546Spatrick     DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions());
739061da546Spatrick 
740061da546Spatrick     if (!valobj_sp->GetTargetSP()->GetDisplayRuntimeSupportValues() &&
741061da546Spatrick         valobj_sp->IsRuntimeSupportValue())
742061da546Spatrick       return;
743061da546Spatrick 
744061da546Spatrick     switch (var_sp->GetScope()) {
745061da546Spatrick     case eValueTypeVariableGlobal:
746061da546Spatrick       if (m_option_variable.show_scope)
747061da546Spatrick         s.PutCString("GLOBAL: ");
748061da546Spatrick       break;
749061da546Spatrick 
750061da546Spatrick     case eValueTypeVariableStatic:
751061da546Spatrick       if (m_option_variable.show_scope)
752061da546Spatrick         s.PutCString("STATIC: ");
753061da546Spatrick       break;
754061da546Spatrick 
755061da546Spatrick     case eValueTypeVariableArgument:
756061da546Spatrick       if (m_option_variable.show_scope)
757061da546Spatrick         s.PutCString("   ARG: ");
758061da546Spatrick       break;
759061da546Spatrick 
760061da546Spatrick     case eValueTypeVariableLocal:
761061da546Spatrick       if (m_option_variable.show_scope)
762061da546Spatrick         s.PutCString(" LOCAL: ");
763061da546Spatrick       break;
764061da546Spatrick 
765061da546Spatrick     case eValueTypeVariableThreadLocal:
766061da546Spatrick       if (m_option_variable.show_scope)
767061da546Spatrick         s.PutCString("THREAD: ");
768061da546Spatrick       break;
769061da546Spatrick 
770061da546Spatrick     default:
771061da546Spatrick       break;
772061da546Spatrick     }
773061da546Spatrick 
774061da546Spatrick     if (m_option_variable.show_decl) {
775061da546Spatrick       bool show_fullpaths = false;
776061da546Spatrick       bool show_module = true;
777061da546Spatrick       if (var_sp->DumpDeclaration(&s, show_fullpaths, show_module))
778061da546Spatrick         s.PutCString(": ");
779061da546Spatrick     }
780061da546Spatrick 
781061da546Spatrick     const Format format = m_option_format.GetFormat();
782061da546Spatrick     if (format != eFormatDefault)
783061da546Spatrick       options.SetFormat(format);
784061da546Spatrick 
785061da546Spatrick     options.SetRootValueObjectName(root_name);
786061da546Spatrick 
787061da546Spatrick     valobj_sp->Dump(s, options);
788061da546Spatrick   }
789061da546Spatrick 
GetVariableCallback(void * baton,const char * name,VariableList & variable_list)790061da546Spatrick   static size_t GetVariableCallback(void *baton, const char *name,
791061da546Spatrick                                     VariableList &variable_list) {
792061da546Spatrick     size_t old_size = variable_list.GetSize();
793061da546Spatrick     Target *target = static_cast<Target *>(baton);
794061da546Spatrick     if (target)
795061da546Spatrick       target->GetImages().FindGlobalVariables(ConstString(name), UINT32_MAX,
796061da546Spatrick                                               variable_list);
797061da546Spatrick     return variable_list.GetSize() - old_size;
798061da546Spatrick   }
799061da546Spatrick 
GetOptions()800061da546Spatrick   Options *GetOptions() override { return &m_option_group; }
801061da546Spatrick 
802061da546Spatrick protected:
DumpGlobalVariableList(const ExecutionContext & exe_ctx,const SymbolContext & sc,const VariableList & variable_list,Stream & s)803061da546Spatrick   void DumpGlobalVariableList(const ExecutionContext &exe_ctx,
804061da546Spatrick                               const SymbolContext &sc,
805061da546Spatrick                               const VariableList &variable_list, Stream &s) {
806061da546Spatrick     if (variable_list.Empty())
807061da546Spatrick       return;
808061da546Spatrick     if (sc.module_sp) {
809061da546Spatrick       if (sc.comp_unit) {
810061da546Spatrick         s.Format("Global variables for {0} in {1}:\n",
811061da546Spatrick                  sc.comp_unit->GetPrimaryFile(), sc.module_sp->GetFileSpec());
812061da546Spatrick       } else {
813061da546Spatrick         s.Printf("Global variables for %s\n",
814061da546Spatrick                  sc.module_sp->GetFileSpec().GetPath().c_str());
815061da546Spatrick       }
816061da546Spatrick     } else if (sc.comp_unit) {
817061da546Spatrick       s.Format("Global variables for {0}\n", sc.comp_unit->GetPrimaryFile());
818061da546Spatrick     }
819061da546Spatrick 
820061da546Spatrick     for (VariableSP var_sp : variable_list) {
821061da546Spatrick       if (!var_sp)
822061da546Spatrick         continue;
823061da546Spatrick       ValueObjectSP valobj_sp(ValueObjectVariable::Create(
824061da546Spatrick           exe_ctx.GetBestExecutionContextScope(), var_sp));
825061da546Spatrick 
826061da546Spatrick       if (valobj_sp)
827061da546Spatrick         DumpValueObject(s, var_sp, valobj_sp, var_sp->GetName().GetCString());
828061da546Spatrick     }
829061da546Spatrick   }
830061da546Spatrick 
DoExecute(Args & args,CommandReturnObject & result)831061da546Spatrick   bool DoExecute(Args &args, CommandReturnObject &result) override {
832061da546Spatrick     Target *target = m_exe_ctx.GetTargetPtr();
833061da546Spatrick     const size_t argc = args.GetArgumentCount();
834061da546Spatrick     Stream &s = result.GetOutputStream();
835061da546Spatrick 
836061da546Spatrick     if (argc > 0) {
837dda28197Spatrick       for (const Args::ArgEntry &arg : args) {
838061da546Spatrick         VariableList variable_list;
839061da546Spatrick         ValueObjectList valobj_list;
840061da546Spatrick 
841061da546Spatrick         size_t matches = 0;
842061da546Spatrick         bool use_var_name = false;
843061da546Spatrick         if (m_option_variable.use_regex) {
844be691f3bSpatrick           RegularExpression regex(arg.ref());
845061da546Spatrick           if (!regex.IsValid()) {
846061da546Spatrick             result.GetErrorStream().Printf(
847dda28197Spatrick                 "error: invalid regular expression: '%s'\n", arg.c_str());
848061da546Spatrick             return false;
849061da546Spatrick           }
850061da546Spatrick           use_var_name = true;
851061da546Spatrick           target->GetImages().FindGlobalVariables(regex, UINT32_MAX,
852061da546Spatrick                                                   variable_list);
853061da546Spatrick           matches = variable_list.GetSize();
854061da546Spatrick         } else {
855061da546Spatrick           Status error(Variable::GetValuesForVariableExpressionPath(
856dda28197Spatrick               arg.c_str(), m_exe_ctx.GetBestExecutionContextScope(),
857061da546Spatrick               GetVariableCallback, target, variable_list, valobj_list));
858061da546Spatrick           matches = variable_list.GetSize();
859061da546Spatrick         }
860061da546Spatrick 
861061da546Spatrick         if (matches == 0) {
862be691f3bSpatrick           result.AppendErrorWithFormat("can't find global variable '%s'",
863be691f3bSpatrick                                        arg.c_str());
864061da546Spatrick           return false;
865061da546Spatrick         } else {
866061da546Spatrick           for (uint32_t global_idx = 0; global_idx < matches; ++global_idx) {
867061da546Spatrick             VariableSP var_sp(variable_list.GetVariableAtIndex(global_idx));
868061da546Spatrick             if (var_sp) {
869061da546Spatrick               ValueObjectSP valobj_sp(
870061da546Spatrick                   valobj_list.GetValueObjectAtIndex(global_idx));
871061da546Spatrick               if (!valobj_sp)
872061da546Spatrick                 valobj_sp = ValueObjectVariable::Create(
873061da546Spatrick                     m_exe_ctx.GetBestExecutionContextScope(), var_sp);
874061da546Spatrick 
875061da546Spatrick               if (valobj_sp)
876061da546Spatrick                 DumpValueObject(s, var_sp, valobj_sp,
877061da546Spatrick                                 use_var_name ? var_sp->GetName().GetCString()
878dda28197Spatrick                                              : arg.c_str());
879061da546Spatrick             }
880061da546Spatrick           }
881061da546Spatrick         }
882061da546Spatrick       }
883061da546Spatrick     } else {
884061da546Spatrick       const FileSpecList &compile_units =
885061da546Spatrick           m_option_compile_units.GetOptionValue().GetCurrentValue();
886061da546Spatrick       const FileSpecList &shlibs =
887061da546Spatrick           m_option_shared_libraries.GetOptionValue().GetCurrentValue();
888061da546Spatrick       SymbolContextList sc_list;
889061da546Spatrick       const size_t num_compile_units = compile_units.GetSize();
890061da546Spatrick       const size_t num_shlibs = shlibs.GetSize();
891061da546Spatrick       if (num_compile_units == 0 && num_shlibs == 0) {
892061da546Spatrick         bool success = false;
893061da546Spatrick         StackFrame *frame = m_exe_ctx.GetFramePtr();
894061da546Spatrick         CompileUnit *comp_unit = nullptr;
895061da546Spatrick         if (frame) {
896061da546Spatrick           SymbolContext sc = frame->GetSymbolContext(eSymbolContextCompUnit);
897be691f3bSpatrick           comp_unit = sc.comp_unit;
898061da546Spatrick           if (sc.comp_unit) {
899061da546Spatrick             const bool can_create = true;
900061da546Spatrick             VariableListSP comp_unit_varlist_sp(
901061da546Spatrick                 sc.comp_unit->GetVariableList(can_create));
902061da546Spatrick             if (comp_unit_varlist_sp) {
903061da546Spatrick               size_t count = comp_unit_varlist_sp->GetSize();
904061da546Spatrick               if (count > 0) {
905061da546Spatrick                 DumpGlobalVariableList(m_exe_ctx, sc, *comp_unit_varlist_sp, s);
906061da546Spatrick                 success = true;
907061da546Spatrick               }
908061da546Spatrick             }
909061da546Spatrick           }
910061da546Spatrick         }
911061da546Spatrick         if (!success) {
912061da546Spatrick           if (frame) {
913061da546Spatrick             if (comp_unit)
914061da546Spatrick               result.AppendErrorWithFormatv(
915061da546Spatrick                   "no global variables in current compile unit: {0}\n",
916061da546Spatrick                   comp_unit->GetPrimaryFile());
917061da546Spatrick             else
918061da546Spatrick               result.AppendErrorWithFormat(
919061da546Spatrick                   "no debug information for frame %u\n",
920061da546Spatrick                   frame->GetFrameIndex());
921061da546Spatrick           } else
922061da546Spatrick             result.AppendError("'target variable' takes one or more global "
923061da546Spatrick                                "variable names as arguments\n");
924061da546Spatrick         }
925061da546Spatrick       } else {
926061da546Spatrick         SymbolContextList sc_list;
927061da546Spatrick         // We have one or more compile unit or shlib
928061da546Spatrick         if (num_shlibs > 0) {
929061da546Spatrick           for (size_t shlib_idx = 0; shlib_idx < num_shlibs; ++shlib_idx) {
930061da546Spatrick             const FileSpec module_file(shlibs.GetFileSpecAtIndex(shlib_idx));
931061da546Spatrick             ModuleSpec module_spec(module_file);
932061da546Spatrick 
933061da546Spatrick             ModuleSP module_sp(
934061da546Spatrick                 target->GetImages().FindFirstModule(module_spec));
935061da546Spatrick             if (module_sp) {
936061da546Spatrick               if (num_compile_units > 0) {
937061da546Spatrick                 for (size_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
938061da546Spatrick                   module_sp->FindCompileUnits(
939061da546Spatrick                       compile_units.GetFileSpecAtIndex(cu_idx), sc_list);
940061da546Spatrick               } else {
941061da546Spatrick                 SymbolContext sc;
942061da546Spatrick                 sc.module_sp = module_sp;
943061da546Spatrick                 sc_list.Append(sc);
944061da546Spatrick               }
945061da546Spatrick             } else {
946061da546Spatrick               // Didn't find matching shlib/module in target...
947061da546Spatrick               result.AppendErrorWithFormat(
948061da546Spatrick                   "target doesn't contain the specified shared library: %s\n",
949061da546Spatrick                   module_file.GetPath().c_str());
950061da546Spatrick             }
951061da546Spatrick           }
952061da546Spatrick         } else {
953061da546Spatrick           // No shared libraries, we just want to find globals for the compile
954061da546Spatrick           // units files that were specified
955061da546Spatrick           for (size_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
956061da546Spatrick             target->GetImages().FindCompileUnits(
957061da546Spatrick                 compile_units.GetFileSpecAtIndex(cu_idx), sc_list);
958061da546Spatrick         }
959061da546Spatrick 
960061da546Spatrick         const uint32_t num_scs = sc_list.GetSize();
961061da546Spatrick         if (num_scs > 0) {
962061da546Spatrick           SymbolContext sc;
963061da546Spatrick           for (uint32_t sc_idx = 0; sc_idx < num_scs; ++sc_idx) {
964061da546Spatrick             if (sc_list.GetContextAtIndex(sc_idx, sc)) {
965061da546Spatrick               if (sc.comp_unit) {
966061da546Spatrick                 const bool can_create = true;
967061da546Spatrick                 VariableListSP comp_unit_varlist_sp(
968061da546Spatrick                     sc.comp_unit->GetVariableList(can_create));
969061da546Spatrick                 if (comp_unit_varlist_sp)
970061da546Spatrick                   DumpGlobalVariableList(m_exe_ctx, sc, *comp_unit_varlist_sp,
971061da546Spatrick                                          s);
972061da546Spatrick               } else if (sc.module_sp) {
973061da546Spatrick                 // Get all global variables for this module
974061da546Spatrick                 lldb_private::RegularExpression all_globals_regex(
975061da546Spatrick                     llvm::StringRef(
976061da546Spatrick                         ".")); // Any global with at least one character
977061da546Spatrick                 VariableList variable_list;
978061da546Spatrick                 sc.module_sp->FindGlobalVariables(all_globals_regex, UINT32_MAX,
979061da546Spatrick                                                   variable_list);
980061da546Spatrick                 DumpGlobalVariableList(m_exe_ctx, sc, variable_list, s);
981061da546Spatrick               }
982061da546Spatrick             }
983061da546Spatrick           }
984061da546Spatrick         }
985061da546Spatrick       }
986061da546Spatrick     }
987061da546Spatrick 
988*f6aab3d8Srobert     m_interpreter.PrintWarningsIfNecessary(result.GetOutputStream(),
989*f6aab3d8Srobert                                            m_cmd_name);
990061da546Spatrick 
991061da546Spatrick     return result.Succeeded();
992061da546Spatrick   }
993061da546Spatrick 
994061da546Spatrick   OptionGroupOptions m_option_group;
995061da546Spatrick   OptionGroupVariable m_option_variable;
996061da546Spatrick   OptionGroupFormat m_option_format;
997061da546Spatrick   OptionGroupFileList m_option_compile_units;
998061da546Spatrick   OptionGroupFileList m_option_shared_libraries;
999061da546Spatrick   OptionGroupValueObjectDisplay m_varobj_options;
1000061da546Spatrick };
1001061da546Spatrick 
1002061da546Spatrick #pragma mark CommandObjectTargetModulesSearchPathsAdd
1003061da546Spatrick 
1004061da546Spatrick class CommandObjectTargetModulesSearchPathsAdd : public CommandObjectParsed {
1005061da546Spatrick public:
CommandObjectTargetModulesSearchPathsAdd(CommandInterpreter & interpreter)1006061da546Spatrick   CommandObjectTargetModulesSearchPathsAdd(CommandInterpreter &interpreter)
1007061da546Spatrick       : CommandObjectParsed(interpreter, "target modules search-paths add",
1008061da546Spatrick                             "Add new image search paths substitution pairs to "
1009061da546Spatrick                             "the current target.",
1010061da546Spatrick                             nullptr, eCommandRequiresTarget) {
1011061da546Spatrick     CommandArgumentEntry arg;
1012061da546Spatrick     CommandArgumentData old_prefix_arg;
1013061da546Spatrick     CommandArgumentData new_prefix_arg;
1014061da546Spatrick 
1015061da546Spatrick     // Define the first variant of this arg pair.
1016061da546Spatrick     old_prefix_arg.arg_type = eArgTypeOldPathPrefix;
1017061da546Spatrick     old_prefix_arg.arg_repetition = eArgRepeatPairPlus;
1018061da546Spatrick 
1019061da546Spatrick     // Define the first variant of this arg pair.
1020061da546Spatrick     new_prefix_arg.arg_type = eArgTypeNewPathPrefix;
1021061da546Spatrick     new_prefix_arg.arg_repetition = eArgRepeatPairPlus;
1022061da546Spatrick 
1023061da546Spatrick     // There are two required arguments that must always occur together, i.e.
1024061da546Spatrick     // an argument "pair".  Because they must always occur together, they are
1025061da546Spatrick     // treated as two variants of one argument rather than two independent
1026061da546Spatrick     // arguments.  Push them both into the first argument position for
1027061da546Spatrick     // m_arguments...
1028061da546Spatrick 
1029061da546Spatrick     arg.push_back(old_prefix_arg);
1030061da546Spatrick     arg.push_back(new_prefix_arg);
1031061da546Spatrick 
1032061da546Spatrick     m_arguments.push_back(arg);
1033061da546Spatrick   }
1034061da546Spatrick 
1035061da546Spatrick   ~CommandObjectTargetModulesSearchPathsAdd() override = default;
1036061da546Spatrick 
1037061da546Spatrick protected:
DoExecute(Args & command,CommandReturnObject & result)1038061da546Spatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
1039061da546Spatrick     Target *target = &GetSelectedTarget();
1040061da546Spatrick     const size_t argc = command.GetArgumentCount();
1041061da546Spatrick     if (argc & 1) {
1042061da546Spatrick       result.AppendError("add requires an even number of arguments\n");
1043061da546Spatrick     } else {
1044061da546Spatrick       for (size_t i = 0; i < argc; i += 2) {
1045061da546Spatrick         const char *from = command.GetArgumentAtIndex(i);
1046061da546Spatrick         const char *to = command.GetArgumentAtIndex(i + 1);
1047061da546Spatrick 
1048061da546Spatrick         if (from[0] && to[0]) {
1049*f6aab3d8Srobert           Log *log = GetLog(LLDBLog::Host);
1050061da546Spatrick           if (log) {
1051061da546Spatrick             LLDB_LOGF(log,
1052061da546Spatrick                       "target modules search path adding ImageSearchPath "
1053061da546Spatrick                       "pair: '%s' -> '%s'",
1054061da546Spatrick                       from, to);
1055061da546Spatrick           }
1056061da546Spatrick           bool last_pair = ((argc - i) == 2);
1057061da546Spatrick           target->GetImageSearchPathList().Append(
1058*f6aab3d8Srobert               from, to, last_pair); // Notify if this is the last pair
1059061da546Spatrick           result.SetStatus(eReturnStatusSuccessFinishNoResult);
1060061da546Spatrick         } else {
1061061da546Spatrick           if (from[0])
1062061da546Spatrick             result.AppendError("<path-prefix> can't be empty\n");
1063061da546Spatrick           else
1064061da546Spatrick             result.AppendError("<new-path-prefix> can't be empty\n");
1065061da546Spatrick         }
1066061da546Spatrick       }
1067061da546Spatrick     }
1068061da546Spatrick     return result.Succeeded();
1069061da546Spatrick   }
1070061da546Spatrick };
1071061da546Spatrick 
1072061da546Spatrick #pragma mark CommandObjectTargetModulesSearchPathsClear
1073061da546Spatrick 
1074061da546Spatrick class CommandObjectTargetModulesSearchPathsClear : public CommandObjectParsed {
1075061da546Spatrick public:
CommandObjectTargetModulesSearchPathsClear(CommandInterpreter & interpreter)1076061da546Spatrick   CommandObjectTargetModulesSearchPathsClear(CommandInterpreter &interpreter)
1077061da546Spatrick       : CommandObjectParsed(interpreter, "target modules search-paths clear",
1078061da546Spatrick                             "Clear all current image search path substitution "
1079061da546Spatrick                             "pairs from the current target.",
1080061da546Spatrick                             "target modules search-paths clear",
1081061da546Spatrick                             eCommandRequiresTarget) {}
1082061da546Spatrick 
1083061da546Spatrick   ~CommandObjectTargetModulesSearchPathsClear() override = default;
1084061da546Spatrick 
1085061da546Spatrick protected:
DoExecute(Args & command,CommandReturnObject & result)1086061da546Spatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
1087061da546Spatrick     Target *target = &GetSelectedTarget();
1088061da546Spatrick     bool notify = true;
1089061da546Spatrick     target->GetImageSearchPathList().Clear(notify);
1090061da546Spatrick     result.SetStatus(eReturnStatusSuccessFinishNoResult);
1091061da546Spatrick     return result.Succeeded();
1092061da546Spatrick   }
1093061da546Spatrick };
1094061da546Spatrick 
1095061da546Spatrick #pragma mark CommandObjectTargetModulesSearchPathsInsert
1096061da546Spatrick 
1097061da546Spatrick class CommandObjectTargetModulesSearchPathsInsert : public CommandObjectParsed {
1098061da546Spatrick public:
CommandObjectTargetModulesSearchPathsInsert(CommandInterpreter & interpreter)1099061da546Spatrick   CommandObjectTargetModulesSearchPathsInsert(CommandInterpreter &interpreter)
1100061da546Spatrick       : CommandObjectParsed(interpreter, "target modules search-paths insert",
1101061da546Spatrick                             "Insert a new image search path substitution pair "
1102061da546Spatrick                             "into the current target at the specified index.",
1103061da546Spatrick                             nullptr, eCommandRequiresTarget) {
1104061da546Spatrick     CommandArgumentEntry arg1;
1105061da546Spatrick     CommandArgumentEntry arg2;
1106061da546Spatrick     CommandArgumentData index_arg;
1107061da546Spatrick     CommandArgumentData old_prefix_arg;
1108061da546Spatrick     CommandArgumentData new_prefix_arg;
1109061da546Spatrick 
1110061da546Spatrick     // Define the first and only variant of this arg.
1111061da546Spatrick     index_arg.arg_type = eArgTypeIndex;
1112061da546Spatrick     index_arg.arg_repetition = eArgRepeatPlain;
1113061da546Spatrick 
1114061da546Spatrick     // Put the one and only variant into the first arg for m_arguments:
1115061da546Spatrick     arg1.push_back(index_arg);
1116061da546Spatrick 
1117061da546Spatrick     // Define the first variant of this arg pair.
1118061da546Spatrick     old_prefix_arg.arg_type = eArgTypeOldPathPrefix;
1119061da546Spatrick     old_prefix_arg.arg_repetition = eArgRepeatPairPlus;
1120061da546Spatrick 
1121061da546Spatrick     // Define the first variant of this arg pair.
1122061da546Spatrick     new_prefix_arg.arg_type = eArgTypeNewPathPrefix;
1123061da546Spatrick     new_prefix_arg.arg_repetition = eArgRepeatPairPlus;
1124061da546Spatrick 
1125061da546Spatrick     // There are two required arguments that must always occur together, i.e.
1126061da546Spatrick     // an argument "pair".  Because they must always occur together, they are
1127061da546Spatrick     // treated as two variants of one argument rather than two independent
1128061da546Spatrick     // arguments.  Push them both into the same argument position for
1129061da546Spatrick     // m_arguments...
1130061da546Spatrick 
1131061da546Spatrick     arg2.push_back(old_prefix_arg);
1132061da546Spatrick     arg2.push_back(new_prefix_arg);
1133061da546Spatrick 
1134061da546Spatrick     // Add arguments to m_arguments.
1135061da546Spatrick     m_arguments.push_back(arg1);
1136061da546Spatrick     m_arguments.push_back(arg2);
1137061da546Spatrick   }
1138061da546Spatrick 
1139061da546Spatrick   ~CommandObjectTargetModulesSearchPathsInsert() override = default;
1140061da546Spatrick 
1141be691f3bSpatrick   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)1142be691f3bSpatrick   HandleArgumentCompletion(CompletionRequest &request,
1143be691f3bSpatrick                            OptionElementVector &opt_element_vector) override {
1144be691f3bSpatrick     if (!m_exe_ctx.HasTargetScope() || request.GetCursorIndex() != 0)
1145be691f3bSpatrick       return;
1146be691f3bSpatrick 
1147be691f3bSpatrick     Target *target = m_exe_ctx.GetTargetPtr();
1148be691f3bSpatrick     const PathMappingList &list = target->GetImageSearchPathList();
1149be691f3bSpatrick     const size_t num = list.GetSize();
1150be691f3bSpatrick     ConstString old_path, new_path;
1151be691f3bSpatrick     for (size_t i = 0; i < num; ++i) {
1152be691f3bSpatrick       if (!list.GetPathsAtIndex(i, old_path, new_path))
1153be691f3bSpatrick         break;
1154be691f3bSpatrick       StreamString strm;
1155be691f3bSpatrick       strm << old_path << " -> " << new_path;
1156be691f3bSpatrick       request.TryCompleteCurrentArg(std::to_string(i), strm.GetString());
1157be691f3bSpatrick     }
1158be691f3bSpatrick   }
1159be691f3bSpatrick 
1160061da546Spatrick protected:
DoExecute(Args & command,CommandReturnObject & result)1161061da546Spatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
1162061da546Spatrick     Target *target = &GetSelectedTarget();
1163061da546Spatrick     size_t argc = command.GetArgumentCount();
1164061da546Spatrick     // check for at least 3 arguments and an odd number of parameters
1165061da546Spatrick     if (argc >= 3 && argc & 1) {
1166dda28197Spatrick       uint32_t insert_idx;
1167061da546Spatrick 
1168dda28197Spatrick       if (!llvm::to_integer(command.GetArgumentAtIndex(0), insert_idx)) {
1169061da546Spatrick         result.AppendErrorWithFormat(
1170061da546Spatrick             "<index> parameter is not an integer: '%s'.\n",
1171061da546Spatrick             command.GetArgumentAtIndex(0));
1172061da546Spatrick         return result.Succeeded();
1173061da546Spatrick       }
1174061da546Spatrick 
1175061da546Spatrick       // shift off the index
1176061da546Spatrick       command.Shift();
1177061da546Spatrick       argc = command.GetArgumentCount();
1178061da546Spatrick 
1179061da546Spatrick       for (uint32_t i = 0; i < argc; i += 2, ++insert_idx) {
1180061da546Spatrick         const char *from = command.GetArgumentAtIndex(i);
1181061da546Spatrick         const char *to = command.GetArgumentAtIndex(i + 1);
1182061da546Spatrick 
1183061da546Spatrick         if (from[0] && to[0]) {
1184061da546Spatrick           bool last_pair = ((argc - i) == 2);
1185*f6aab3d8Srobert           target->GetImageSearchPathList().Insert(from, to, insert_idx,
1186*f6aab3d8Srobert                                                   last_pair);
1187061da546Spatrick           result.SetStatus(eReturnStatusSuccessFinishNoResult);
1188061da546Spatrick         } else {
1189061da546Spatrick           if (from[0])
1190061da546Spatrick             result.AppendError("<path-prefix> can't be empty\n");
1191061da546Spatrick           else
1192061da546Spatrick             result.AppendError("<new-path-prefix> can't be empty\n");
1193061da546Spatrick           return false;
1194061da546Spatrick         }
1195061da546Spatrick       }
1196061da546Spatrick     } else {
1197061da546Spatrick       result.AppendError("insert requires at least three arguments\n");
1198061da546Spatrick       return result.Succeeded();
1199061da546Spatrick     }
1200061da546Spatrick     return result.Succeeded();
1201061da546Spatrick   }
1202061da546Spatrick };
1203061da546Spatrick 
1204061da546Spatrick #pragma mark CommandObjectTargetModulesSearchPathsList
1205061da546Spatrick 
1206061da546Spatrick class CommandObjectTargetModulesSearchPathsList : public CommandObjectParsed {
1207061da546Spatrick public:
CommandObjectTargetModulesSearchPathsList(CommandInterpreter & interpreter)1208061da546Spatrick   CommandObjectTargetModulesSearchPathsList(CommandInterpreter &interpreter)
1209061da546Spatrick       : CommandObjectParsed(interpreter, "target modules search-paths list",
1210061da546Spatrick                             "List all current image search path substitution "
1211061da546Spatrick                             "pairs in the current target.",
1212061da546Spatrick                             "target modules search-paths list",
1213061da546Spatrick                             eCommandRequiresTarget) {}
1214061da546Spatrick 
1215061da546Spatrick   ~CommandObjectTargetModulesSearchPathsList() override = default;
1216061da546Spatrick 
1217061da546Spatrick protected:
DoExecute(Args & command,CommandReturnObject & result)1218061da546Spatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
1219061da546Spatrick     Target *target = &GetSelectedTarget();
1220061da546Spatrick 
1221061da546Spatrick     target->GetImageSearchPathList().Dump(&result.GetOutputStream());
1222061da546Spatrick     result.SetStatus(eReturnStatusSuccessFinishResult);
1223061da546Spatrick     return result.Succeeded();
1224061da546Spatrick   }
1225061da546Spatrick };
1226061da546Spatrick 
1227061da546Spatrick #pragma mark CommandObjectTargetModulesSearchPathsQuery
1228061da546Spatrick 
1229061da546Spatrick class CommandObjectTargetModulesSearchPathsQuery : public CommandObjectParsed {
1230061da546Spatrick public:
CommandObjectTargetModulesSearchPathsQuery(CommandInterpreter & interpreter)1231061da546Spatrick   CommandObjectTargetModulesSearchPathsQuery(CommandInterpreter &interpreter)
1232061da546Spatrick       : CommandObjectParsed(
1233061da546Spatrick             interpreter, "target modules search-paths query",
1234061da546Spatrick             "Transform a path using the first applicable image search path.",
1235061da546Spatrick             nullptr, eCommandRequiresTarget) {
1236061da546Spatrick     CommandArgumentEntry arg;
1237061da546Spatrick     CommandArgumentData path_arg;
1238061da546Spatrick 
1239061da546Spatrick     // Define the first (and only) variant of this arg.
1240061da546Spatrick     path_arg.arg_type = eArgTypeDirectoryName;
1241061da546Spatrick     path_arg.arg_repetition = eArgRepeatPlain;
1242061da546Spatrick 
1243061da546Spatrick     // There is only one variant this argument could be; put it into the
1244061da546Spatrick     // argument entry.
1245061da546Spatrick     arg.push_back(path_arg);
1246061da546Spatrick 
1247061da546Spatrick     // Push the data for the first argument into the m_arguments vector.
1248061da546Spatrick     m_arguments.push_back(arg);
1249061da546Spatrick   }
1250061da546Spatrick 
1251061da546Spatrick   ~CommandObjectTargetModulesSearchPathsQuery() override = default;
1252061da546Spatrick 
1253061da546Spatrick protected:
DoExecute(Args & command,CommandReturnObject & result)1254061da546Spatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
1255061da546Spatrick     Target *target = &GetSelectedTarget();
1256061da546Spatrick     if (command.GetArgumentCount() != 1) {
1257061da546Spatrick       result.AppendError("query requires one argument\n");
1258061da546Spatrick       return result.Succeeded();
1259061da546Spatrick     }
1260061da546Spatrick 
1261061da546Spatrick     ConstString orig(command.GetArgumentAtIndex(0));
1262061da546Spatrick     ConstString transformed;
1263061da546Spatrick     if (target->GetImageSearchPathList().RemapPath(orig, transformed))
1264061da546Spatrick       result.GetOutputStream().Printf("%s\n", transformed.GetCString());
1265061da546Spatrick     else
1266061da546Spatrick       result.GetOutputStream().Printf("%s\n", orig.GetCString());
1267061da546Spatrick 
1268061da546Spatrick     result.SetStatus(eReturnStatusSuccessFinishResult);
1269061da546Spatrick     return result.Succeeded();
1270061da546Spatrick   }
1271061da546Spatrick };
1272061da546Spatrick 
1273061da546Spatrick // Static Helper functions
DumpModuleArchitecture(Stream & strm,Module * module,bool full_triple,uint32_t width)1274061da546Spatrick static void DumpModuleArchitecture(Stream &strm, Module *module,
1275061da546Spatrick                                    bool full_triple, uint32_t width) {
1276061da546Spatrick   if (module) {
1277061da546Spatrick     StreamString arch_strm;
1278061da546Spatrick 
1279061da546Spatrick     if (full_triple)
1280061da546Spatrick       module->GetArchitecture().DumpTriple(arch_strm.AsRawOstream());
1281061da546Spatrick     else
1282061da546Spatrick       arch_strm.PutCString(module->GetArchitecture().GetArchitectureName());
1283dda28197Spatrick     std::string arch_str = std::string(arch_strm.GetString());
1284061da546Spatrick 
1285061da546Spatrick     if (width)
1286061da546Spatrick       strm.Printf("%-*s", width, arch_str.c_str());
1287061da546Spatrick     else
1288061da546Spatrick       strm.PutCString(arch_str);
1289061da546Spatrick   }
1290061da546Spatrick }
1291061da546Spatrick 
DumpModuleUUID(Stream & strm,Module * module)1292061da546Spatrick static void DumpModuleUUID(Stream &strm, Module *module) {
1293061da546Spatrick   if (module && module->GetUUID().IsValid())
1294061da546Spatrick     module->GetUUID().Dump(&strm);
1295061da546Spatrick   else
1296061da546Spatrick     strm.PutCString("                                    ");
1297061da546Spatrick }
1298061da546Spatrick 
DumpCompileUnitLineTable(CommandInterpreter & interpreter,Stream & strm,Module * module,const FileSpec & file_spec,lldb::DescriptionLevel desc_level)1299061da546Spatrick static uint32_t DumpCompileUnitLineTable(CommandInterpreter &interpreter,
1300061da546Spatrick                                          Stream &strm, Module *module,
1301061da546Spatrick                                          const FileSpec &file_spec,
1302061da546Spatrick                                          lldb::DescriptionLevel desc_level) {
1303061da546Spatrick   uint32_t num_matches = 0;
1304061da546Spatrick   if (module) {
1305061da546Spatrick     SymbolContextList sc_list;
1306061da546Spatrick     num_matches = module->ResolveSymbolContextsForFileSpec(
1307061da546Spatrick         file_spec, 0, false, eSymbolContextCompUnit, sc_list);
1308061da546Spatrick 
1309061da546Spatrick     for (uint32_t i = 0; i < num_matches; ++i) {
1310061da546Spatrick       SymbolContext sc;
1311061da546Spatrick       if (sc_list.GetContextAtIndex(i, sc)) {
1312061da546Spatrick         if (i > 0)
1313061da546Spatrick           strm << "\n\n";
1314061da546Spatrick 
1315061da546Spatrick         strm << "Line table for " << sc.comp_unit->GetPrimaryFile() << " in `"
1316061da546Spatrick              << module->GetFileSpec().GetFilename() << "\n";
1317061da546Spatrick         LineTable *line_table = sc.comp_unit->GetLineTable();
1318061da546Spatrick         if (line_table)
1319061da546Spatrick           line_table->GetDescription(
1320061da546Spatrick               &strm, interpreter.GetExecutionContext().GetTargetPtr(),
1321061da546Spatrick               desc_level);
1322061da546Spatrick         else
1323061da546Spatrick           strm << "No line table";
1324061da546Spatrick       }
1325061da546Spatrick     }
1326061da546Spatrick   }
1327061da546Spatrick   return num_matches;
1328061da546Spatrick }
1329061da546Spatrick 
DumpFullpath(Stream & strm,const FileSpec * file_spec_ptr,uint32_t width)1330061da546Spatrick static void DumpFullpath(Stream &strm, const FileSpec *file_spec_ptr,
1331061da546Spatrick                          uint32_t width) {
1332061da546Spatrick   if (file_spec_ptr) {
1333061da546Spatrick     if (width > 0) {
1334061da546Spatrick       std::string fullpath = file_spec_ptr->GetPath();
1335061da546Spatrick       strm.Printf("%-*s", width, fullpath.c_str());
1336061da546Spatrick       return;
1337061da546Spatrick     } else {
1338061da546Spatrick       file_spec_ptr->Dump(strm.AsRawOstream());
1339061da546Spatrick       return;
1340061da546Spatrick     }
1341061da546Spatrick   }
1342061da546Spatrick   // Keep the width spacing correct if things go wrong...
1343061da546Spatrick   if (width > 0)
1344061da546Spatrick     strm.Printf("%-*s", width, "");
1345061da546Spatrick }
1346061da546Spatrick 
DumpDirectory(Stream & strm,const FileSpec * file_spec_ptr,uint32_t width)1347061da546Spatrick static void DumpDirectory(Stream &strm, const FileSpec *file_spec_ptr,
1348061da546Spatrick                           uint32_t width) {
1349061da546Spatrick   if (file_spec_ptr) {
1350061da546Spatrick     if (width > 0)
1351061da546Spatrick       strm.Printf("%-*s", width, file_spec_ptr->GetDirectory().AsCString(""));
1352061da546Spatrick     else
1353061da546Spatrick       file_spec_ptr->GetDirectory().Dump(&strm);
1354061da546Spatrick     return;
1355061da546Spatrick   }
1356061da546Spatrick   // Keep the width spacing correct if things go wrong...
1357061da546Spatrick   if (width > 0)
1358061da546Spatrick     strm.Printf("%-*s", width, "");
1359061da546Spatrick }
1360061da546Spatrick 
DumpBasename(Stream & strm,const FileSpec * file_spec_ptr,uint32_t width)1361061da546Spatrick static void DumpBasename(Stream &strm, const FileSpec *file_spec_ptr,
1362061da546Spatrick                          uint32_t width) {
1363061da546Spatrick   if (file_spec_ptr) {
1364061da546Spatrick     if (width > 0)
1365061da546Spatrick       strm.Printf("%-*s", width, file_spec_ptr->GetFilename().AsCString(""));
1366061da546Spatrick     else
1367061da546Spatrick       file_spec_ptr->GetFilename().Dump(&strm);
1368061da546Spatrick     return;
1369061da546Spatrick   }
1370061da546Spatrick   // Keep the width spacing correct if things go wrong...
1371061da546Spatrick   if (width > 0)
1372061da546Spatrick     strm.Printf("%-*s", width, "");
1373061da546Spatrick }
1374061da546Spatrick 
DumpModuleObjfileHeaders(Stream & strm,ModuleList & module_list)1375061da546Spatrick static size_t DumpModuleObjfileHeaders(Stream &strm, ModuleList &module_list) {
1376061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex());
1377061da546Spatrick   const size_t num_modules = module_list.GetSize();
1378be691f3bSpatrick   if (num_modules == 0)
1379be691f3bSpatrick     return 0;
1380be691f3bSpatrick 
1381be691f3bSpatrick   size_t num_dumped = 0;
1382be691f3bSpatrick   strm.Format("Dumping headers for {0} module(s).\n", num_modules);
1383061da546Spatrick   strm.IndentMore();
1384be691f3bSpatrick   for (ModuleSP module_sp : module_list.ModulesNoLocking()) {
1385be691f3bSpatrick     if (module_sp) {
1386061da546Spatrick       if (num_dumped++ > 0) {
1387061da546Spatrick         strm.EOL();
1388061da546Spatrick         strm.EOL();
1389061da546Spatrick       }
1390be691f3bSpatrick       ObjectFile *objfile = module_sp->GetObjectFile();
1391061da546Spatrick       if (objfile)
1392061da546Spatrick         objfile->Dump(&strm);
1393061da546Spatrick       else {
1394061da546Spatrick         strm.Format("No object file for module: {0:F}\n",
1395be691f3bSpatrick                     module_sp->GetFileSpec());
1396061da546Spatrick       }
1397061da546Spatrick     }
1398061da546Spatrick   }
1399061da546Spatrick   strm.IndentLess();
1400061da546Spatrick   return num_dumped;
1401061da546Spatrick }
1402061da546Spatrick 
DumpModuleSymtab(CommandInterpreter & interpreter,Stream & strm,Module * module,SortOrder sort_order,Mangled::NamePreference name_preference)1403061da546Spatrick static void DumpModuleSymtab(CommandInterpreter &interpreter, Stream &strm,
1404061da546Spatrick                              Module *module, SortOrder sort_order,
1405061da546Spatrick                              Mangled::NamePreference name_preference) {
1406061da546Spatrick   if (!module)
1407061da546Spatrick     return;
1408061da546Spatrick   if (Symtab *symtab = module->GetSymtab())
1409061da546Spatrick     symtab->Dump(&strm, interpreter.GetExecutionContext().GetTargetPtr(),
1410061da546Spatrick                  sort_order, name_preference);
1411061da546Spatrick }
1412061da546Spatrick 
DumpModuleSections(CommandInterpreter & interpreter,Stream & strm,Module * module)1413061da546Spatrick static void DumpModuleSections(CommandInterpreter &interpreter, Stream &strm,
1414061da546Spatrick                                Module *module) {
1415061da546Spatrick   if (module) {
1416061da546Spatrick     SectionList *section_list = module->GetSectionList();
1417061da546Spatrick     if (section_list) {
1418061da546Spatrick       strm.Printf("Sections for '%s' (%s):\n",
1419061da546Spatrick                   module->GetSpecificationDescription().c_str(),
1420061da546Spatrick                   module->GetArchitecture().GetArchitectureName());
1421dda28197Spatrick       section_list->Dump(strm.AsRawOstream(), strm.GetIndentLevel() + 2,
1422061da546Spatrick                          interpreter.GetExecutionContext().GetTargetPtr(), true,
1423061da546Spatrick                          UINT32_MAX);
1424061da546Spatrick     }
1425061da546Spatrick   }
1426061da546Spatrick }
1427061da546Spatrick 
DumpModuleSymbolFile(Stream & strm,Module * module)1428061da546Spatrick static bool DumpModuleSymbolFile(Stream &strm, Module *module) {
1429061da546Spatrick   if (module) {
1430061da546Spatrick     if (SymbolFile *symbol_file = module->GetSymbolFile(true)) {
1431061da546Spatrick       symbol_file->Dump(strm);
1432061da546Spatrick       return true;
1433061da546Spatrick     }
1434061da546Spatrick   }
1435061da546Spatrick   return false;
1436061da546Spatrick }
1437061da546Spatrick 
DumpAddress(ExecutionContextScope * exe_scope,const Address & so_addr,bool verbose,bool all_ranges,Stream & strm)1438061da546Spatrick static void DumpAddress(ExecutionContextScope *exe_scope,
1439*f6aab3d8Srobert                         const Address &so_addr, bool verbose, bool all_ranges,
1440*f6aab3d8Srobert                         Stream &strm) {
1441061da546Spatrick   strm.IndentMore();
1442061da546Spatrick   strm.Indent("    Address: ");
1443061da546Spatrick   so_addr.Dump(&strm, exe_scope, Address::DumpStyleModuleWithFileAddress);
1444061da546Spatrick   strm.PutCString(" (");
1445061da546Spatrick   so_addr.Dump(&strm, exe_scope, Address::DumpStyleSectionNameOffset);
1446061da546Spatrick   strm.PutCString(")\n");
1447061da546Spatrick   strm.Indent("    Summary: ");
1448061da546Spatrick   const uint32_t save_indent = strm.GetIndentLevel();
1449061da546Spatrick   strm.SetIndentLevel(save_indent + 13);
1450061da546Spatrick   so_addr.Dump(&strm, exe_scope, Address::DumpStyleResolvedDescription);
1451061da546Spatrick   strm.SetIndentLevel(save_indent);
1452061da546Spatrick   // Print out detailed address information when verbose is enabled
1453061da546Spatrick   if (verbose) {
1454061da546Spatrick     strm.EOL();
1455*f6aab3d8Srobert     so_addr.Dump(&strm, exe_scope, Address::DumpStyleDetailedSymbolContext,
1456*f6aab3d8Srobert                  Address::DumpStyleInvalid, UINT32_MAX, all_ranges);
1457061da546Spatrick   }
1458061da546Spatrick   strm.IndentLess();
1459061da546Spatrick }
1460061da546Spatrick 
LookupAddressInModule(CommandInterpreter & interpreter,Stream & strm,Module * module,uint32_t resolve_mask,lldb::addr_t raw_addr,lldb::addr_t offset,bool verbose,bool all_ranges)1461061da546Spatrick static bool LookupAddressInModule(CommandInterpreter &interpreter, Stream &strm,
1462061da546Spatrick                                   Module *module, uint32_t resolve_mask,
1463061da546Spatrick                                   lldb::addr_t raw_addr, lldb::addr_t offset,
1464*f6aab3d8Srobert                                   bool verbose, bool all_ranges) {
1465061da546Spatrick   if (module) {
1466061da546Spatrick     lldb::addr_t addr = raw_addr - offset;
1467061da546Spatrick     Address so_addr;
1468061da546Spatrick     SymbolContext sc;
1469061da546Spatrick     Target *target = interpreter.GetExecutionContext().GetTargetPtr();
1470061da546Spatrick     if (target && !target->GetSectionLoadList().IsEmpty()) {
1471061da546Spatrick       if (!target->GetSectionLoadList().ResolveLoadAddress(addr, so_addr))
1472061da546Spatrick         return false;
1473061da546Spatrick       else if (so_addr.GetModule().get() != module)
1474061da546Spatrick         return false;
1475061da546Spatrick     } else {
1476061da546Spatrick       if (!module->ResolveFileAddress(addr, so_addr))
1477061da546Spatrick         return false;
1478061da546Spatrick     }
1479061da546Spatrick 
1480061da546Spatrick     ExecutionContextScope *exe_scope =
1481061da546Spatrick         interpreter.GetExecutionContext().GetBestExecutionContextScope();
1482*f6aab3d8Srobert     DumpAddress(exe_scope, so_addr, verbose, all_ranges, strm);
1483061da546Spatrick     //        strm.IndentMore();
1484061da546Spatrick     //        strm.Indent ("    Address: ");
1485061da546Spatrick     //        so_addr.Dump (&strm, exe_scope,
1486061da546Spatrick     //        Address::DumpStyleModuleWithFileAddress);
1487061da546Spatrick     //        strm.PutCString (" (");
1488061da546Spatrick     //        so_addr.Dump (&strm, exe_scope,
1489061da546Spatrick     //        Address::DumpStyleSectionNameOffset);
1490061da546Spatrick     //        strm.PutCString (")\n");
1491061da546Spatrick     //        strm.Indent ("    Summary: ");
1492061da546Spatrick     //        const uint32_t save_indent = strm.GetIndentLevel ();
1493061da546Spatrick     //        strm.SetIndentLevel (save_indent + 13);
1494061da546Spatrick     //        so_addr.Dump (&strm, exe_scope,
1495061da546Spatrick     //        Address::DumpStyleResolvedDescription);
1496061da546Spatrick     //        strm.SetIndentLevel (save_indent);
1497061da546Spatrick     //        // Print out detailed address information when verbose is enabled
1498061da546Spatrick     //        if (verbose)
1499061da546Spatrick     //        {
1500061da546Spatrick     //            strm.EOL();
1501061da546Spatrick     //            so_addr.Dump (&strm, exe_scope,
1502061da546Spatrick     //            Address::DumpStyleDetailedSymbolContext);
1503061da546Spatrick     //        }
1504061da546Spatrick     //        strm.IndentLess();
1505061da546Spatrick     return true;
1506061da546Spatrick   }
1507061da546Spatrick 
1508061da546Spatrick   return false;
1509061da546Spatrick }
1510061da546Spatrick 
LookupSymbolInModule(CommandInterpreter & interpreter,Stream & strm,Module * module,const char * name,bool name_is_regex,bool verbose,bool all_ranges)1511061da546Spatrick static uint32_t LookupSymbolInModule(CommandInterpreter &interpreter,
1512061da546Spatrick                                      Stream &strm, Module *module,
1513061da546Spatrick                                      const char *name, bool name_is_regex,
1514*f6aab3d8Srobert                                      bool verbose, bool all_ranges) {
1515061da546Spatrick   if (!module)
1516061da546Spatrick     return 0;
1517061da546Spatrick 
1518061da546Spatrick   Symtab *symtab = module->GetSymtab();
1519061da546Spatrick   if (!symtab)
1520061da546Spatrick     return 0;
1521061da546Spatrick 
1522061da546Spatrick   SymbolContext sc;
1523061da546Spatrick   std::vector<uint32_t> match_indexes;
1524061da546Spatrick   ConstString symbol_name(name);
1525061da546Spatrick   uint32_t num_matches = 0;
1526061da546Spatrick   if (name_is_regex) {
1527061da546Spatrick     RegularExpression name_regexp(symbol_name.GetStringRef());
1528061da546Spatrick     num_matches = symtab->AppendSymbolIndexesMatchingRegExAndType(
1529061da546Spatrick         name_regexp, eSymbolTypeAny, match_indexes);
1530061da546Spatrick   } else {
1531061da546Spatrick     num_matches =
1532061da546Spatrick         symtab->AppendSymbolIndexesWithName(symbol_name, match_indexes);
1533061da546Spatrick   }
1534061da546Spatrick 
1535061da546Spatrick   if (num_matches > 0) {
1536061da546Spatrick     strm.Indent();
1537061da546Spatrick     strm.Printf("%u symbols match %s'%s' in ", num_matches,
1538061da546Spatrick                 name_is_regex ? "the regular expression " : "", name);
1539061da546Spatrick     DumpFullpath(strm, &module->GetFileSpec(), 0);
1540061da546Spatrick     strm.PutCString(":\n");
1541061da546Spatrick     strm.IndentMore();
1542061da546Spatrick     for (uint32_t i = 0; i < num_matches; ++i) {
1543061da546Spatrick       Symbol *symbol = symtab->SymbolAtIndex(match_indexes[i]);
1544*f6aab3d8Srobert       if (symbol) {
1545*f6aab3d8Srobert         if (symbol->ValueIsAddress()) {
1546061da546Spatrick           DumpAddress(
1547061da546Spatrick               interpreter.GetExecutionContext().GetBestExecutionContextScope(),
1548*f6aab3d8Srobert               symbol->GetAddressRef(), verbose, all_ranges, strm);
1549*f6aab3d8Srobert           strm.EOL();
1550*f6aab3d8Srobert         } else {
1551*f6aab3d8Srobert           strm.IndentMore();
1552*f6aab3d8Srobert           strm.Indent("    Name: ");
1553*f6aab3d8Srobert           strm.PutCString(symbol->GetDisplayName().GetStringRef());
1554*f6aab3d8Srobert           strm.EOL();
1555*f6aab3d8Srobert           strm.Indent("    Value: ");
1556*f6aab3d8Srobert           strm.Printf("0x%16.16" PRIx64 "\n", symbol->GetRawValue());
1557*f6aab3d8Srobert           if (symbol->GetByteSizeIsValid()) {
1558*f6aab3d8Srobert             strm.Indent("    Size: ");
1559*f6aab3d8Srobert             strm.Printf("0x%16.16" PRIx64 "\n", symbol->GetByteSize());
1560*f6aab3d8Srobert           }
1561*f6aab3d8Srobert           strm.IndentLess();
1562*f6aab3d8Srobert         }
1563061da546Spatrick       }
1564061da546Spatrick     }
1565061da546Spatrick     strm.IndentLess();
1566061da546Spatrick   }
1567061da546Spatrick   return num_matches;
1568061da546Spatrick }
1569061da546Spatrick 
DumpSymbolContextList(ExecutionContextScope * exe_scope,Stream & strm,SymbolContextList & sc_list,bool verbose,bool all_ranges)1570061da546Spatrick static void DumpSymbolContextList(ExecutionContextScope *exe_scope,
1571061da546Spatrick                                   Stream &strm, SymbolContextList &sc_list,
1572*f6aab3d8Srobert                                   bool verbose, bool all_ranges) {
1573061da546Spatrick   strm.IndentMore();
1574061da546Spatrick 
1575061da546Spatrick   const uint32_t num_matches = sc_list.GetSize();
1576061da546Spatrick 
1577061da546Spatrick   for (uint32_t i = 0; i < num_matches; ++i) {
1578061da546Spatrick     SymbolContext sc;
1579061da546Spatrick     if (sc_list.GetContextAtIndex(i, sc)) {
1580061da546Spatrick       AddressRange range;
1581061da546Spatrick 
1582061da546Spatrick       sc.GetAddressRange(eSymbolContextEverything, 0, true, range);
1583061da546Spatrick 
1584*f6aab3d8Srobert       DumpAddress(exe_scope, range.GetBaseAddress(), verbose, all_ranges, strm);
1585061da546Spatrick     }
1586061da546Spatrick   }
1587061da546Spatrick   strm.IndentLess();
1588061da546Spatrick }
1589061da546Spatrick 
LookupFunctionInModule(CommandInterpreter & interpreter,Stream & strm,Module * module,const char * name,bool name_is_regex,const ModuleFunctionSearchOptions & options,bool verbose,bool all_ranges)1590061da546Spatrick static size_t LookupFunctionInModule(CommandInterpreter &interpreter,
1591061da546Spatrick                                      Stream &strm, Module *module,
1592061da546Spatrick                                      const char *name, bool name_is_regex,
1593*f6aab3d8Srobert                                      const ModuleFunctionSearchOptions &options,
1594*f6aab3d8Srobert                                      bool verbose, bool all_ranges) {
1595061da546Spatrick   if (module && name && name[0]) {
1596061da546Spatrick     SymbolContextList sc_list;
1597061da546Spatrick     size_t num_matches = 0;
1598061da546Spatrick     if (name_is_regex) {
1599061da546Spatrick       RegularExpression function_name_regex((llvm::StringRef(name)));
1600*f6aab3d8Srobert       module->FindFunctions(function_name_regex, options, sc_list);
1601061da546Spatrick     } else {
1602061da546Spatrick       ConstString function_name(name);
1603dda28197Spatrick       module->FindFunctions(function_name, CompilerDeclContext(),
1604*f6aab3d8Srobert                             eFunctionNameTypeAuto, options, sc_list);
1605061da546Spatrick     }
1606061da546Spatrick     num_matches = sc_list.GetSize();
1607061da546Spatrick     if (num_matches) {
1608061da546Spatrick       strm.Indent();
1609061da546Spatrick       strm.Printf("%" PRIu64 " match%s found in ", (uint64_t)num_matches,
1610061da546Spatrick                   num_matches > 1 ? "es" : "");
1611061da546Spatrick       DumpFullpath(strm, &module->GetFileSpec(), 0);
1612061da546Spatrick       strm.PutCString(":\n");
1613061da546Spatrick       DumpSymbolContextList(
1614061da546Spatrick           interpreter.GetExecutionContext().GetBestExecutionContextScope(),
1615*f6aab3d8Srobert           strm, sc_list, verbose, all_ranges);
1616061da546Spatrick     }
1617061da546Spatrick     return num_matches;
1618061da546Spatrick   }
1619061da546Spatrick   return 0;
1620061da546Spatrick }
1621061da546Spatrick 
LookupTypeInModule(Target * target,CommandInterpreter & interpreter,Stream & strm,Module * module,const char * name_cstr,bool name_is_regex)1622be691f3bSpatrick static size_t LookupTypeInModule(Target *target,
1623be691f3bSpatrick                                  CommandInterpreter &interpreter, Stream &strm,
1624061da546Spatrick                                  Module *module, const char *name_cstr,
1625061da546Spatrick                                  bool name_is_regex) {
1626061da546Spatrick   TypeList type_list;
1627061da546Spatrick   if (module && name_cstr && name_cstr[0]) {
1628061da546Spatrick     const uint32_t max_num_matches = UINT32_MAX;
1629061da546Spatrick     bool name_is_fully_qualified = false;
1630061da546Spatrick 
1631061da546Spatrick     ConstString name(name_cstr);
1632061da546Spatrick     llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files;
1633061da546Spatrick     module->FindTypes(name, name_is_fully_qualified, max_num_matches,
1634061da546Spatrick                       searched_symbol_files, type_list);
1635061da546Spatrick 
1636061da546Spatrick     if (type_list.Empty())
1637061da546Spatrick       return 0;
1638061da546Spatrick 
1639*f6aab3d8Srobert     const uint64_t num_matches = type_list.GetSize();
1640*f6aab3d8Srobert 
1641061da546Spatrick     strm.Indent();
1642*f6aab3d8Srobert     strm.Printf("%" PRIu64 " match%s found in ", num_matches,
1643061da546Spatrick                 num_matches > 1 ? "es" : "");
1644061da546Spatrick     DumpFullpath(strm, &module->GetFileSpec(), 0);
1645061da546Spatrick     strm.PutCString(":\n");
1646061da546Spatrick     for (TypeSP type_sp : type_list.Types()) {
1647061da546Spatrick       if (!type_sp)
1648061da546Spatrick         continue;
1649061da546Spatrick       // Resolve the clang type so that any forward references to types
1650061da546Spatrick       // that haven't yet been parsed will get parsed.
1651061da546Spatrick       type_sp->GetFullCompilerType();
1652be691f3bSpatrick       type_sp->GetDescription(&strm, eDescriptionLevelFull, true, target);
1653061da546Spatrick       // Print all typedef chains
1654061da546Spatrick       TypeSP typedef_type_sp(type_sp);
1655061da546Spatrick       TypeSP typedefed_type_sp(typedef_type_sp->GetTypedefType());
1656061da546Spatrick       while (typedefed_type_sp) {
1657061da546Spatrick         strm.EOL();
1658061da546Spatrick         strm.Printf("     typedef '%s': ",
1659061da546Spatrick                     typedef_type_sp->GetName().GetCString());
1660061da546Spatrick         typedefed_type_sp->GetFullCompilerType();
1661be691f3bSpatrick         typedefed_type_sp->GetDescription(&strm, eDescriptionLevelFull, true,
1662be691f3bSpatrick                                           target);
1663061da546Spatrick         typedef_type_sp = typedefed_type_sp;
1664061da546Spatrick         typedefed_type_sp = typedef_type_sp->GetTypedefType();
1665061da546Spatrick       }
1666061da546Spatrick       strm.EOL();
1667061da546Spatrick     }
1668*f6aab3d8Srobert   }
1669061da546Spatrick   return type_list.GetSize();
1670061da546Spatrick }
1671061da546Spatrick 
LookupTypeHere(Target * target,CommandInterpreter & interpreter,Stream & strm,Module & module,const char * name_cstr,bool name_is_regex)1672be691f3bSpatrick static size_t LookupTypeHere(Target *target, CommandInterpreter &interpreter,
1673be691f3bSpatrick                              Stream &strm, Module &module,
1674be691f3bSpatrick                              const char *name_cstr, bool name_is_regex) {
1675061da546Spatrick   TypeList type_list;
1676061da546Spatrick   const uint32_t max_num_matches = UINT32_MAX;
1677061da546Spatrick   bool name_is_fully_qualified = false;
1678061da546Spatrick 
1679061da546Spatrick   ConstString name(name_cstr);
1680061da546Spatrick   llvm::DenseSet<SymbolFile *> searched_symbol_files;
1681061da546Spatrick   module.FindTypes(name, name_is_fully_qualified, max_num_matches,
1682061da546Spatrick                    searched_symbol_files, type_list);
1683061da546Spatrick 
1684061da546Spatrick   if (type_list.Empty())
1685061da546Spatrick     return 0;
1686061da546Spatrick 
1687061da546Spatrick   strm.Indent();
1688061da546Spatrick   strm.PutCString("Best match found in ");
1689061da546Spatrick   DumpFullpath(strm, &module.GetFileSpec(), 0);
1690061da546Spatrick   strm.PutCString(":\n");
1691061da546Spatrick 
1692061da546Spatrick   TypeSP type_sp(type_list.GetTypeAtIndex(0));
1693061da546Spatrick   if (type_sp) {
1694061da546Spatrick     // Resolve the clang type so that any forward references to types that
1695061da546Spatrick     // haven't yet been parsed will get parsed.
1696061da546Spatrick     type_sp->GetFullCompilerType();
1697be691f3bSpatrick     type_sp->GetDescription(&strm, eDescriptionLevelFull, true, target);
1698be691f3bSpatrick     // Print all typedef chains.
1699061da546Spatrick     TypeSP typedef_type_sp(type_sp);
1700061da546Spatrick     TypeSP typedefed_type_sp(typedef_type_sp->GetTypedefType());
1701061da546Spatrick     while (typedefed_type_sp) {
1702061da546Spatrick       strm.EOL();
1703061da546Spatrick       strm.Printf("     typedef '%s': ",
1704061da546Spatrick                   typedef_type_sp->GetName().GetCString());
1705061da546Spatrick       typedefed_type_sp->GetFullCompilerType();
1706be691f3bSpatrick       typedefed_type_sp->GetDescription(&strm, eDescriptionLevelFull, true,
1707be691f3bSpatrick                                         target);
1708061da546Spatrick       typedef_type_sp = typedefed_type_sp;
1709061da546Spatrick       typedefed_type_sp = typedef_type_sp->GetTypedefType();
1710061da546Spatrick     }
1711061da546Spatrick   }
1712061da546Spatrick   strm.EOL();
1713061da546Spatrick   return type_list.GetSize();
1714061da546Spatrick }
1715061da546Spatrick 
LookupFileAndLineInModule(CommandInterpreter & interpreter,Stream & strm,Module * module,const FileSpec & file_spec,uint32_t line,bool check_inlines,bool verbose,bool all_ranges)1716061da546Spatrick static uint32_t LookupFileAndLineInModule(CommandInterpreter &interpreter,
1717061da546Spatrick                                           Stream &strm, Module *module,
1718061da546Spatrick                                           const FileSpec &file_spec,
1719061da546Spatrick                                           uint32_t line, bool check_inlines,
1720*f6aab3d8Srobert                                           bool verbose, bool all_ranges) {
1721061da546Spatrick   if (module && file_spec) {
1722061da546Spatrick     SymbolContextList sc_list;
1723061da546Spatrick     const uint32_t num_matches = module->ResolveSymbolContextsForFileSpec(
1724061da546Spatrick         file_spec, line, check_inlines, eSymbolContextEverything, sc_list);
1725061da546Spatrick     if (num_matches > 0) {
1726061da546Spatrick       strm.Indent();
1727061da546Spatrick       strm.Printf("%u match%s found in ", num_matches,
1728061da546Spatrick                   num_matches > 1 ? "es" : "");
1729061da546Spatrick       strm << file_spec;
1730061da546Spatrick       if (line > 0)
1731061da546Spatrick         strm.Printf(":%u", line);
1732061da546Spatrick       strm << " in ";
1733061da546Spatrick       DumpFullpath(strm, &module->GetFileSpec(), 0);
1734061da546Spatrick       strm.PutCString(":\n");
1735061da546Spatrick       DumpSymbolContextList(
1736061da546Spatrick           interpreter.GetExecutionContext().GetBestExecutionContextScope(),
1737*f6aab3d8Srobert           strm, sc_list, verbose, all_ranges);
1738061da546Spatrick       return num_matches;
1739061da546Spatrick     }
1740061da546Spatrick   }
1741061da546Spatrick   return 0;
1742061da546Spatrick }
1743061da546Spatrick 
FindModulesByName(Target * target,const char * module_name,ModuleList & module_list,bool check_global_list)1744061da546Spatrick static size_t FindModulesByName(Target *target, const char *module_name,
1745061da546Spatrick                                 ModuleList &module_list,
1746061da546Spatrick                                 bool check_global_list) {
1747061da546Spatrick   FileSpec module_file_spec(module_name);
1748061da546Spatrick   ModuleSpec module_spec(module_file_spec);
1749061da546Spatrick 
1750061da546Spatrick   const size_t initial_size = module_list.GetSize();
1751061da546Spatrick 
1752061da546Spatrick   if (check_global_list) {
1753061da546Spatrick     // Check the global list
1754061da546Spatrick     std::lock_guard<std::recursive_mutex> guard(
1755061da546Spatrick         Module::GetAllocationModuleCollectionMutex());
1756061da546Spatrick     const size_t num_modules = Module::GetNumberAllocatedModules();
1757061da546Spatrick     ModuleSP module_sp;
1758061da546Spatrick     for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
1759061da546Spatrick       Module *module = Module::GetAllocatedModuleAtIndex(image_idx);
1760061da546Spatrick 
1761061da546Spatrick       if (module) {
1762061da546Spatrick         if (module->MatchesModuleSpec(module_spec)) {
1763061da546Spatrick           module_sp = module->shared_from_this();
1764061da546Spatrick           module_list.AppendIfNeeded(module_sp);
1765061da546Spatrick         }
1766061da546Spatrick       }
1767061da546Spatrick     }
1768061da546Spatrick   } else {
1769061da546Spatrick     if (target) {
1770061da546Spatrick       target->GetImages().FindModules(module_spec, module_list);
1771061da546Spatrick       const size_t num_matches = module_list.GetSize();
1772061da546Spatrick 
1773061da546Spatrick       // Not found in our module list for our target, check the main shared
1774061da546Spatrick       // module list in case it is a extra file used somewhere else
1775061da546Spatrick       if (num_matches == 0) {
1776061da546Spatrick         module_spec.GetArchitecture() = target->GetArchitecture();
1777061da546Spatrick         ModuleList::FindSharedModules(module_spec, module_list);
1778061da546Spatrick       }
1779061da546Spatrick     } else {
1780061da546Spatrick       ModuleList::FindSharedModules(module_spec, module_list);
1781061da546Spatrick     }
1782061da546Spatrick   }
1783061da546Spatrick 
1784061da546Spatrick   return module_list.GetSize() - initial_size;
1785061da546Spatrick }
1786061da546Spatrick 
1787061da546Spatrick #pragma mark CommandObjectTargetModulesModuleAutoComplete
1788061da546Spatrick 
1789061da546Spatrick // A base command object class that can auto complete with module file
1790061da546Spatrick // paths
1791061da546Spatrick 
1792061da546Spatrick class CommandObjectTargetModulesModuleAutoComplete
1793061da546Spatrick     : public CommandObjectParsed {
1794061da546Spatrick public:
CommandObjectTargetModulesModuleAutoComplete(CommandInterpreter & interpreter,const char * name,const char * help,const char * syntax,uint32_t flags=0)1795061da546Spatrick   CommandObjectTargetModulesModuleAutoComplete(CommandInterpreter &interpreter,
1796061da546Spatrick                                                const char *name,
1797061da546Spatrick                                                const char *help,
1798061da546Spatrick                                                const char *syntax,
1799061da546Spatrick                                                uint32_t flags = 0)
1800061da546Spatrick       : CommandObjectParsed(interpreter, name, help, syntax, flags) {
1801061da546Spatrick     CommandArgumentEntry arg;
1802061da546Spatrick     CommandArgumentData file_arg;
1803061da546Spatrick 
1804061da546Spatrick     // Define the first (and only) variant of this arg.
1805061da546Spatrick     file_arg.arg_type = eArgTypeFilename;
1806061da546Spatrick     file_arg.arg_repetition = eArgRepeatStar;
1807061da546Spatrick 
1808061da546Spatrick     // There is only one variant this argument could be; put it into the
1809061da546Spatrick     // argument entry.
1810061da546Spatrick     arg.push_back(file_arg);
1811061da546Spatrick 
1812061da546Spatrick     // Push the data for the first argument into the m_arguments vector.
1813061da546Spatrick     m_arguments.push_back(arg);
1814061da546Spatrick   }
1815061da546Spatrick 
1816061da546Spatrick   ~CommandObjectTargetModulesModuleAutoComplete() override = default;
1817061da546Spatrick 
1818061da546Spatrick   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)1819061da546Spatrick   HandleArgumentCompletion(CompletionRequest &request,
1820061da546Spatrick                            OptionElementVector &opt_element_vector) override {
1821061da546Spatrick     CommandCompletions::InvokeCommonCompletionCallbacks(
1822061da546Spatrick         GetCommandInterpreter(), CommandCompletions::eModuleCompletion, request,
1823061da546Spatrick         nullptr);
1824061da546Spatrick   }
1825061da546Spatrick };
1826061da546Spatrick 
1827061da546Spatrick #pragma mark CommandObjectTargetModulesSourceFileAutoComplete
1828061da546Spatrick 
1829061da546Spatrick // A base command object class that can auto complete with module source
1830061da546Spatrick // file paths
1831061da546Spatrick 
1832061da546Spatrick class CommandObjectTargetModulesSourceFileAutoComplete
1833061da546Spatrick     : public CommandObjectParsed {
1834061da546Spatrick public:
CommandObjectTargetModulesSourceFileAutoComplete(CommandInterpreter & interpreter,const char * name,const char * help,const char * syntax,uint32_t flags)1835061da546Spatrick   CommandObjectTargetModulesSourceFileAutoComplete(
1836061da546Spatrick       CommandInterpreter &interpreter, const char *name, const char *help,
1837061da546Spatrick       const char *syntax, uint32_t flags)
1838061da546Spatrick       : CommandObjectParsed(interpreter, name, help, syntax, flags) {
1839061da546Spatrick     CommandArgumentEntry arg;
1840061da546Spatrick     CommandArgumentData source_file_arg;
1841061da546Spatrick 
1842061da546Spatrick     // Define the first (and only) variant of this arg.
1843061da546Spatrick     source_file_arg.arg_type = eArgTypeSourceFile;
1844061da546Spatrick     source_file_arg.arg_repetition = eArgRepeatPlus;
1845061da546Spatrick 
1846061da546Spatrick     // There is only one variant this argument could be; put it into the
1847061da546Spatrick     // argument entry.
1848061da546Spatrick     arg.push_back(source_file_arg);
1849061da546Spatrick 
1850061da546Spatrick     // Push the data for the first argument into the m_arguments vector.
1851061da546Spatrick     m_arguments.push_back(arg);
1852061da546Spatrick   }
1853061da546Spatrick 
1854061da546Spatrick   ~CommandObjectTargetModulesSourceFileAutoComplete() override = default;
1855061da546Spatrick 
1856061da546Spatrick   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)1857061da546Spatrick   HandleArgumentCompletion(CompletionRequest &request,
1858061da546Spatrick                            OptionElementVector &opt_element_vector) override {
1859061da546Spatrick     CommandCompletions::InvokeCommonCompletionCallbacks(
1860061da546Spatrick         GetCommandInterpreter(), CommandCompletions::eSourceFileCompletion,
1861061da546Spatrick         request, nullptr);
1862061da546Spatrick   }
1863061da546Spatrick };
1864061da546Spatrick 
1865061da546Spatrick #pragma mark CommandObjectTargetModulesDumpObjfile
1866061da546Spatrick 
1867061da546Spatrick class CommandObjectTargetModulesDumpObjfile
1868061da546Spatrick     : public CommandObjectTargetModulesModuleAutoComplete {
1869061da546Spatrick public:
CommandObjectTargetModulesDumpObjfile(CommandInterpreter & interpreter)1870061da546Spatrick   CommandObjectTargetModulesDumpObjfile(CommandInterpreter &interpreter)
1871061da546Spatrick       : CommandObjectTargetModulesModuleAutoComplete(
1872061da546Spatrick             interpreter, "target modules dump objfile",
1873061da546Spatrick             "Dump the object file headers from one or more target modules.",
1874061da546Spatrick             nullptr, eCommandRequiresTarget) {}
1875061da546Spatrick 
1876061da546Spatrick   ~CommandObjectTargetModulesDumpObjfile() override = default;
1877061da546Spatrick 
1878061da546Spatrick protected:
DoExecute(Args & command,CommandReturnObject & result)1879061da546Spatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
1880061da546Spatrick     Target *target = &GetSelectedTarget();
1881061da546Spatrick 
1882061da546Spatrick     uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
1883061da546Spatrick     result.GetOutputStream().SetAddressByteSize(addr_byte_size);
1884061da546Spatrick     result.GetErrorStream().SetAddressByteSize(addr_byte_size);
1885061da546Spatrick 
1886061da546Spatrick     size_t num_dumped = 0;
1887061da546Spatrick     if (command.GetArgumentCount() == 0) {
1888061da546Spatrick       // Dump all headers for all modules images
1889061da546Spatrick       num_dumped = DumpModuleObjfileHeaders(result.GetOutputStream(),
1890061da546Spatrick                                             target->GetImages());
1891061da546Spatrick       if (num_dumped == 0) {
1892061da546Spatrick         result.AppendError("the target has no associated executable images");
1893061da546Spatrick       }
1894061da546Spatrick     } else {
1895061da546Spatrick       // Find the modules that match the basename or full path.
1896061da546Spatrick       ModuleList module_list;
1897061da546Spatrick       const char *arg_cstr;
1898061da546Spatrick       for (int arg_idx = 0;
1899061da546Spatrick            (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
1900061da546Spatrick            ++arg_idx) {
1901061da546Spatrick         size_t num_matched =
1902061da546Spatrick             FindModulesByName(target, arg_cstr, module_list, true);
1903061da546Spatrick         if (num_matched == 0) {
1904061da546Spatrick           result.AppendWarningWithFormat(
1905061da546Spatrick               "Unable to find an image that matches '%s'.\n", arg_cstr);
1906061da546Spatrick         }
1907061da546Spatrick       }
1908061da546Spatrick       // Dump all the modules we found.
1909061da546Spatrick       num_dumped =
1910061da546Spatrick           DumpModuleObjfileHeaders(result.GetOutputStream(), module_list);
1911061da546Spatrick     }
1912061da546Spatrick 
1913061da546Spatrick     if (num_dumped > 0) {
1914061da546Spatrick       result.SetStatus(eReturnStatusSuccessFinishResult);
1915061da546Spatrick     } else {
1916061da546Spatrick       result.AppendError("no matching executable images found");
1917061da546Spatrick     }
1918061da546Spatrick     return result.Succeeded();
1919061da546Spatrick   }
1920061da546Spatrick };
1921061da546Spatrick 
1922061da546Spatrick #define LLDB_OPTIONS_target_modules_dump_symtab
1923061da546Spatrick #include "CommandOptions.inc"
1924061da546Spatrick 
1925061da546Spatrick class CommandObjectTargetModulesDumpSymtab
1926061da546Spatrick     : public CommandObjectTargetModulesModuleAutoComplete {
1927061da546Spatrick public:
CommandObjectTargetModulesDumpSymtab(CommandInterpreter & interpreter)1928061da546Spatrick   CommandObjectTargetModulesDumpSymtab(CommandInterpreter &interpreter)
1929061da546Spatrick       : CommandObjectTargetModulesModuleAutoComplete(
1930061da546Spatrick             interpreter, "target modules dump symtab",
1931061da546Spatrick             "Dump the symbol table from one or more target modules.", nullptr,
1932*f6aab3d8Srobert             eCommandRequiresTarget) {}
1933061da546Spatrick 
1934061da546Spatrick   ~CommandObjectTargetModulesDumpSymtab() override = default;
1935061da546Spatrick 
GetOptions()1936061da546Spatrick   Options *GetOptions() override { return &m_options; }
1937061da546Spatrick 
1938061da546Spatrick   class CommandOptions : public Options {
1939061da546Spatrick   public:
1940*f6aab3d8Srobert     CommandOptions() = default;
1941061da546Spatrick 
1942061da546Spatrick     ~CommandOptions() override = default;
1943061da546Spatrick 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)1944061da546Spatrick     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1945061da546Spatrick                           ExecutionContext *execution_context) override {
1946061da546Spatrick       Status error;
1947061da546Spatrick       const int short_option = m_getopt_table[option_idx].val;
1948061da546Spatrick 
1949061da546Spatrick       switch (short_option) {
1950061da546Spatrick       case 'm':
1951061da546Spatrick         m_prefer_mangled.SetCurrentValue(true);
1952061da546Spatrick         m_prefer_mangled.SetOptionWasSet();
1953061da546Spatrick         break;
1954061da546Spatrick 
1955061da546Spatrick       case 's':
1956061da546Spatrick         m_sort_order = (SortOrder)OptionArgParser::ToOptionEnum(
1957061da546Spatrick             option_arg, GetDefinitions()[option_idx].enum_values,
1958061da546Spatrick             eSortOrderNone, error);
1959061da546Spatrick         break;
1960061da546Spatrick 
1961061da546Spatrick       default:
1962061da546Spatrick         llvm_unreachable("Unimplemented option");
1963061da546Spatrick       }
1964061da546Spatrick       return error;
1965061da546Spatrick     }
1966061da546Spatrick 
OptionParsingStarting(ExecutionContext * execution_context)1967061da546Spatrick     void OptionParsingStarting(ExecutionContext *execution_context) override {
1968061da546Spatrick       m_sort_order = eSortOrderNone;
1969061da546Spatrick       m_prefer_mangled.Clear();
1970061da546Spatrick     }
1971061da546Spatrick 
GetDefinitions()1972061da546Spatrick     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1973*f6aab3d8Srobert       return llvm::ArrayRef(g_target_modules_dump_symtab_options);
1974061da546Spatrick     }
1975061da546Spatrick 
1976be691f3bSpatrick     SortOrder m_sort_order = eSortOrderNone;
1977061da546Spatrick     OptionValueBoolean m_prefer_mangled = {false, false};
1978061da546Spatrick   };
1979061da546Spatrick 
1980061da546Spatrick protected:
DoExecute(Args & command,CommandReturnObject & result)1981061da546Spatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
1982061da546Spatrick     Target *target = &GetSelectedTarget();
1983061da546Spatrick     uint32_t num_dumped = 0;
1984061da546Spatrick     Mangled::NamePreference name_preference =
1985061da546Spatrick         (m_options.m_prefer_mangled ? Mangled::ePreferMangled
1986061da546Spatrick                                     : Mangled::ePreferDemangled);
1987061da546Spatrick 
1988061da546Spatrick     uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
1989061da546Spatrick     result.GetOutputStream().SetAddressByteSize(addr_byte_size);
1990061da546Spatrick     result.GetErrorStream().SetAddressByteSize(addr_byte_size);
1991061da546Spatrick 
1992061da546Spatrick     if (command.GetArgumentCount() == 0) {
1993061da546Spatrick       // Dump all sections for all modules images
1994be691f3bSpatrick       const ModuleList &module_list = target->GetImages();
1995be691f3bSpatrick       std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex());
1996be691f3bSpatrick       const size_t num_modules = module_list.GetSize();
1997061da546Spatrick       if (num_modules > 0) {
1998be691f3bSpatrick         result.GetOutputStream().Format(
1999be691f3bSpatrick             "Dumping symbol table for {0} modules.\n", num_modules);
2000be691f3bSpatrick         for (ModuleSP module_sp : module_list.ModulesNoLocking()) {
2001061da546Spatrick           if (num_dumped > 0) {
2002061da546Spatrick             result.GetOutputStream().EOL();
2003061da546Spatrick             result.GetOutputStream().EOL();
2004061da546Spatrick           }
2005061da546Spatrick           if (m_interpreter.WasInterrupted())
2006061da546Spatrick             break;
2007061da546Spatrick           num_dumped++;
2008be691f3bSpatrick           DumpModuleSymtab(m_interpreter, result.GetOutputStream(),
2009be691f3bSpatrick                            module_sp.get(), m_options.m_sort_order,
2010be691f3bSpatrick                            name_preference);
2011061da546Spatrick         }
2012061da546Spatrick       } else {
2013061da546Spatrick         result.AppendError("the target has no associated executable images");
2014061da546Spatrick         return false;
2015061da546Spatrick       }
2016061da546Spatrick     } else {
2017061da546Spatrick       // Dump specified images (by basename or fullpath)
2018061da546Spatrick       const char *arg_cstr;
2019061da546Spatrick       for (int arg_idx = 0;
2020061da546Spatrick            (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
2021061da546Spatrick            ++arg_idx) {
2022061da546Spatrick         ModuleList module_list;
2023061da546Spatrick         const size_t num_matches =
2024061da546Spatrick             FindModulesByName(target, arg_cstr, module_list, true);
2025061da546Spatrick         if (num_matches > 0) {
2026be691f3bSpatrick           for (ModuleSP module_sp : module_list.Modules()) {
2027be691f3bSpatrick             if (module_sp) {
2028061da546Spatrick               if (num_dumped > 0) {
2029061da546Spatrick                 result.GetOutputStream().EOL();
2030061da546Spatrick                 result.GetOutputStream().EOL();
2031061da546Spatrick               }
2032061da546Spatrick               if (m_interpreter.WasInterrupted())
2033061da546Spatrick                 break;
2034061da546Spatrick               num_dumped++;
2035be691f3bSpatrick               DumpModuleSymtab(m_interpreter, result.GetOutputStream(),
2036be691f3bSpatrick                                module_sp.get(), m_options.m_sort_order,
2037be691f3bSpatrick                                name_preference);
2038061da546Spatrick             }
2039061da546Spatrick           }
2040061da546Spatrick         } else
2041061da546Spatrick           result.AppendWarningWithFormat(
2042061da546Spatrick               "Unable to find an image that matches '%s'.\n", arg_cstr);
2043061da546Spatrick       }
2044061da546Spatrick     }
2045061da546Spatrick 
2046061da546Spatrick     if (num_dumped > 0)
2047061da546Spatrick       result.SetStatus(eReturnStatusSuccessFinishResult);
2048061da546Spatrick     else {
2049061da546Spatrick       result.AppendError("no matching executable images found");
2050061da546Spatrick     }
2051061da546Spatrick     return result.Succeeded();
2052061da546Spatrick   }
2053061da546Spatrick 
2054061da546Spatrick   CommandOptions m_options;
2055061da546Spatrick };
2056061da546Spatrick 
2057061da546Spatrick #pragma mark CommandObjectTargetModulesDumpSections
2058061da546Spatrick 
2059061da546Spatrick // Image section dumping command
2060061da546Spatrick 
2061061da546Spatrick class CommandObjectTargetModulesDumpSections
2062061da546Spatrick     : public CommandObjectTargetModulesModuleAutoComplete {
2063061da546Spatrick public:
CommandObjectTargetModulesDumpSections(CommandInterpreter & interpreter)2064061da546Spatrick   CommandObjectTargetModulesDumpSections(CommandInterpreter &interpreter)
2065061da546Spatrick       : CommandObjectTargetModulesModuleAutoComplete(
2066061da546Spatrick             interpreter, "target modules dump sections",
2067061da546Spatrick             "Dump the sections from one or more target modules.",
2068061da546Spatrick             //"target modules dump sections [<file1> ...]")
2069061da546Spatrick             nullptr, eCommandRequiresTarget) {}
2070061da546Spatrick 
2071061da546Spatrick   ~CommandObjectTargetModulesDumpSections() override = default;
2072061da546Spatrick 
2073061da546Spatrick protected:
DoExecute(Args & command,CommandReturnObject & result)2074061da546Spatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
2075061da546Spatrick     Target *target = &GetSelectedTarget();
2076061da546Spatrick     uint32_t num_dumped = 0;
2077061da546Spatrick 
2078061da546Spatrick     uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
2079061da546Spatrick     result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2080061da546Spatrick     result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2081061da546Spatrick 
2082061da546Spatrick     if (command.GetArgumentCount() == 0) {
2083061da546Spatrick       // Dump all sections for all modules images
2084061da546Spatrick       const size_t num_modules = target->GetImages().GetSize();
2085be691f3bSpatrick       if (num_modules == 0) {
2086be691f3bSpatrick         result.AppendError("the target has no associated executable images");
2087be691f3bSpatrick         return false;
2088be691f3bSpatrick       }
2089be691f3bSpatrick 
2090be691f3bSpatrick       result.GetOutputStream().Format("Dumping sections for {0} modules.\n",
2091be691f3bSpatrick                                       num_modules);
2092061da546Spatrick       for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
2093061da546Spatrick         if (m_interpreter.WasInterrupted())
2094061da546Spatrick           break;
2095061da546Spatrick         num_dumped++;
2096061da546Spatrick         DumpModuleSections(
2097061da546Spatrick             m_interpreter, result.GetOutputStream(),
2098061da546Spatrick             target->GetImages().GetModulePointerAtIndex(image_idx));
2099061da546Spatrick       }
2100061da546Spatrick     } else {
2101061da546Spatrick       // Dump specified images (by basename or fullpath)
2102061da546Spatrick       const char *arg_cstr;
2103061da546Spatrick       for (int arg_idx = 0;
2104061da546Spatrick            (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
2105061da546Spatrick            ++arg_idx) {
2106061da546Spatrick         ModuleList module_list;
2107061da546Spatrick         const size_t num_matches =
2108061da546Spatrick             FindModulesByName(target, arg_cstr, module_list, true);
2109061da546Spatrick         if (num_matches > 0) {
2110061da546Spatrick           for (size_t i = 0; i < num_matches; ++i) {
2111061da546Spatrick             if (m_interpreter.WasInterrupted())
2112061da546Spatrick               break;
2113061da546Spatrick             Module *module = module_list.GetModulePointerAtIndex(i);
2114061da546Spatrick             if (module) {
2115061da546Spatrick               num_dumped++;
2116061da546Spatrick               DumpModuleSections(m_interpreter, result.GetOutputStream(),
2117061da546Spatrick                                  module);
2118061da546Spatrick             }
2119061da546Spatrick           }
2120061da546Spatrick         } else {
2121061da546Spatrick           // Check the global list
2122061da546Spatrick           std::lock_guard<std::recursive_mutex> guard(
2123061da546Spatrick               Module::GetAllocationModuleCollectionMutex());
2124061da546Spatrick 
2125061da546Spatrick           result.AppendWarningWithFormat(
2126061da546Spatrick               "Unable to find an image that matches '%s'.\n", arg_cstr);
2127061da546Spatrick         }
2128061da546Spatrick       }
2129061da546Spatrick     }
2130061da546Spatrick 
2131061da546Spatrick     if (num_dumped > 0)
2132061da546Spatrick       result.SetStatus(eReturnStatusSuccessFinishResult);
2133061da546Spatrick     else {
2134061da546Spatrick       result.AppendError("no matching executable images found");
2135061da546Spatrick     }
2136061da546Spatrick     return result.Succeeded();
2137061da546Spatrick   }
2138061da546Spatrick };
2139061da546Spatrick 
2140*f6aab3d8Srobert class CommandObjectTargetModulesDumpClangPCMInfo : public CommandObjectParsed {
2141*f6aab3d8Srobert public:
CommandObjectTargetModulesDumpClangPCMInfo(CommandInterpreter & interpreter)2142*f6aab3d8Srobert   CommandObjectTargetModulesDumpClangPCMInfo(CommandInterpreter &interpreter)
2143*f6aab3d8Srobert       : CommandObjectParsed(
2144*f6aab3d8Srobert             interpreter, "target modules dump pcm-info",
2145*f6aab3d8Srobert             "Dump information about the given clang module (pcm).") {
2146*f6aab3d8Srobert     // Take a single file argument.
2147*f6aab3d8Srobert     CommandArgumentData arg{eArgTypeFilename, eArgRepeatPlain};
2148*f6aab3d8Srobert     m_arguments.push_back({arg});
2149*f6aab3d8Srobert   }
2150*f6aab3d8Srobert 
2151*f6aab3d8Srobert   ~CommandObjectTargetModulesDumpClangPCMInfo() override = default;
2152*f6aab3d8Srobert 
2153*f6aab3d8Srobert protected:
DoExecute(Args & command,CommandReturnObject & result)2154*f6aab3d8Srobert   bool DoExecute(Args &command, CommandReturnObject &result) override {
2155*f6aab3d8Srobert     if (command.GetArgumentCount() != 1) {
2156*f6aab3d8Srobert       result.AppendErrorWithFormat("'%s' takes exactly one pcm path argument.",
2157*f6aab3d8Srobert                                    m_cmd_name.c_str());
2158*f6aab3d8Srobert       return false;
2159*f6aab3d8Srobert     }
2160*f6aab3d8Srobert 
2161*f6aab3d8Srobert     const char *pcm_path = command.GetArgumentAtIndex(0);
2162*f6aab3d8Srobert     FileSpec pcm_file{pcm_path};
2163*f6aab3d8Srobert 
2164*f6aab3d8Srobert     if (pcm_file.GetFileNameExtension().GetStringRef() != ".pcm") {
2165*f6aab3d8Srobert       result.AppendError("file must have a .pcm extension");
2166*f6aab3d8Srobert       return false;
2167*f6aab3d8Srobert     }
2168*f6aab3d8Srobert 
2169*f6aab3d8Srobert     if (!FileSystem::Instance().Exists(pcm_file)) {
2170*f6aab3d8Srobert       result.AppendError("pcm file does not exist");
2171*f6aab3d8Srobert       return false;
2172*f6aab3d8Srobert     }
2173*f6aab3d8Srobert 
2174*f6aab3d8Srobert     clang::CompilerInstance compiler;
2175*f6aab3d8Srobert     compiler.createDiagnostics();
2176*f6aab3d8Srobert 
2177*f6aab3d8Srobert     const char *clang_args[] = {"clang", pcm_path};
2178*f6aab3d8Srobert     compiler.setInvocation(clang::createInvocation(clang_args));
2179*f6aab3d8Srobert 
2180*f6aab3d8Srobert     clang::DumpModuleInfoAction dump_module_info;
2181*f6aab3d8Srobert     dump_module_info.OutputStream = &result.GetOutputStream().AsRawOstream();
2182*f6aab3d8Srobert     // DumpModuleInfoAction requires ObjectFilePCHContainerReader.
2183*f6aab3d8Srobert     compiler.getPCHContainerOperations()->registerReader(
2184*f6aab3d8Srobert         std::make_unique<clang::ObjectFilePCHContainerReader>());
2185*f6aab3d8Srobert 
2186*f6aab3d8Srobert     if (compiler.ExecuteAction(dump_module_info))
2187*f6aab3d8Srobert       result.SetStatus(eReturnStatusSuccessFinishResult);
2188*f6aab3d8Srobert 
2189*f6aab3d8Srobert     return result.Succeeded();
2190*f6aab3d8Srobert   }
2191*f6aab3d8Srobert };
2192*f6aab3d8Srobert 
2193dda28197Spatrick #pragma mark CommandObjectTargetModulesDumpClangAST
2194061da546Spatrick 
2195061da546Spatrick // Clang AST dumping command
2196061da546Spatrick 
2197061da546Spatrick class CommandObjectTargetModulesDumpClangAST
2198061da546Spatrick     : public CommandObjectTargetModulesModuleAutoComplete {
2199061da546Spatrick public:
CommandObjectTargetModulesDumpClangAST(CommandInterpreter & interpreter)2200061da546Spatrick   CommandObjectTargetModulesDumpClangAST(CommandInterpreter &interpreter)
2201061da546Spatrick       : CommandObjectTargetModulesModuleAutoComplete(
2202061da546Spatrick             interpreter, "target modules dump ast",
2203061da546Spatrick             "Dump the clang ast for a given module's symbol file.",
2204061da546Spatrick             //"target modules dump ast [<file1> ...]")
2205061da546Spatrick             nullptr, eCommandRequiresTarget) {}
2206061da546Spatrick 
2207061da546Spatrick   ~CommandObjectTargetModulesDumpClangAST() override = default;
2208061da546Spatrick 
2209061da546Spatrick protected:
DoExecute(Args & command,CommandReturnObject & result)2210061da546Spatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
2211061da546Spatrick     Target *target = &GetSelectedTarget();
2212061da546Spatrick 
2213be691f3bSpatrick     const ModuleList &module_list = target->GetImages();
2214be691f3bSpatrick     const size_t num_modules = module_list.GetSize();
2215061da546Spatrick     if (num_modules == 0) {
2216061da546Spatrick       result.AppendError("the target has no associated executable images");
2217061da546Spatrick       return false;
2218061da546Spatrick     }
2219061da546Spatrick 
2220061da546Spatrick     if (command.GetArgumentCount() == 0) {
2221061da546Spatrick       // Dump all ASTs for all modules images
2222be691f3bSpatrick       result.GetOutputStream().Format("Dumping clang ast for {0} modules.\n",
2223be691f3bSpatrick                                       num_modules);
2224be691f3bSpatrick       for (ModuleSP module_sp : module_list.ModulesNoLocking()) {
2225061da546Spatrick         if (m_interpreter.WasInterrupted())
2226061da546Spatrick           break;
2227be691f3bSpatrick         if (SymbolFile *sf = module_sp->GetSymbolFile())
2228061da546Spatrick           sf->DumpClangAST(result.GetOutputStream());
2229061da546Spatrick       }
2230061da546Spatrick       result.SetStatus(eReturnStatusSuccessFinishResult);
2231061da546Spatrick       return true;
2232061da546Spatrick     }
2233061da546Spatrick 
2234061da546Spatrick     // Dump specified ASTs (by basename or fullpath)
2235061da546Spatrick     for (const Args::ArgEntry &arg : command.entries()) {
2236061da546Spatrick       ModuleList module_list;
2237061da546Spatrick       const size_t num_matches =
2238061da546Spatrick           FindModulesByName(target, arg.c_str(), module_list, true);
2239061da546Spatrick       if (num_matches == 0) {
2240061da546Spatrick         // Check the global list
2241061da546Spatrick         std::lock_guard<std::recursive_mutex> guard(
2242061da546Spatrick             Module::GetAllocationModuleCollectionMutex());
2243061da546Spatrick 
2244061da546Spatrick         result.AppendWarningWithFormat(
2245061da546Spatrick             "Unable to find an image that matches '%s'.\n", arg.c_str());
2246061da546Spatrick         continue;
2247061da546Spatrick       }
2248061da546Spatrick 
2249061da546Spatrick       for (size_t i = 0; i < num_matches; ++i) {
2250061da546Spatrick         if (m_interpreter.WasInterrupted())
2251061da546Spatrick           break;
2252061da546Spatrick         Module *m = module_list.GetModulePointerAtIndex(i);
2253061da546Spatrick         if (SymbolFile *sf = m->GetSymbolFile())
2254061da546Spatrick           sf->DumpClangAST(result.GetOutputStream());
2255061da546Spatrick       }
2256061da546Spatrick     }
2257061da546Spatrick     result.SetStatus(eReturnStatusSuccessFinishResult);
2258061da546Spatrick     return true;
2259061da546Spatrick   }
2260061da546Spatrick };
2261061da546Spatrick 
2262061da546Spatrick #pragma mark CommandObjectTargetModulesDumpSymfile
2263061da546Spatrick 
2264061da546Spatrick // Image debug symbol dumping command
2265061da546Spatrick 
2266061da546Spatrick class CommandObjectTargetModulesDumpSymfile
2267061da546Spatrick     : public CommandObjectTargetModulesModuleAutoComplete {
2268061da546Spatrick public:
CommandObjectTargetModulesDumpSymfile(CommandInterpreter & interpreter)2269061da546Spatrick   CommandObjectTargetModulesDumpSymfile(CommandInterpreter &interpreter)
2270061da546Spatrick       : CommandObjectTargetModulesModuleAutoComplete(
2271061da546Spatrick             interpreter, "target modules dump symfile",
2272061da546Spatrick             "Dump the debug symbol file for one or more target modules.",
2273061da546Spatrick             //"target modules dump symfile [<file1> ...]")
2274061da546Spatrick             nullptr, eCommandRequiresTarget) {}
2275061da546Spatrick 
2276061da546Spatrick   ~CommandObjectTargetModulesDumpSymfile() override = default;
2277061da546Spatrick 
2278061da546Spatrick protected:
DoExecute(Args & command,CommandReturnObject & result)2279061da546Spatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
2280061da546Spatrick     Target *target = &GetSelectedTarget();
2281061da546Spatrick     uint32_t num_dumped = 0;
2282061da546Spatrick 
2283061da546Spatrick     uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
2284061da546Spatrick     result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2285061da546Spatrick     result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2286061da546Spatrick 
2287061da546Spatrick     if (command.GetArgumentCount() == 0) {
2288061da546Spatrick       // Dump all sections for all modules images
2289061da546Spatrick       const ModuleList &target_modules = target->GetImages();
2290061da546Spatrick       std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
2291061da546Spatrick       const size_t num_modules = target_modules.GetSize();
2292be691f3bSpatrick       if (num_modules == 0) {
2293be691f3bSpatrick         result.AppendError("the target has no associated executable images");
2294be691f3bSpatrick         return false;
2295be691f3bSpatrick       }
2296be691f3bSpatrick       result.GetOutputStream().Format(
2297be691f3bSpatrick           "Dumping debug symbols for {0} modules.\n", num_modules);
2298be691f3bSpatrick       for (ModuleSP module_sp : target_modules.ModulesNoLocking()) {
2299061da546Spatrick         if (m_interpreter.WasInterrupted())
2300061da546Spatrick           break;
2301be691f3bSpatrick         if (DumpModuleSymbolFile(result.GetOutputStream(), module_sp.get()))
2302061da546Spatrick           num_dumped++;
2303061da546Spatrick       }
2304061da546Spatrick     } else {
2305061da546Spatrick       // Dump specified images (by basename or fullpath)
2306061da546Spatrick       const char *arg_cstr;
2307061da546Spatrick       for (int arg_idx = 0;
2308061da546Spatrick            (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
2309061da546Spatrick            ++arg_idx) {
2310061da546Spatrick         ModuleList module_list;
2311061da546Spatrick         const size_t num_matches =
2312061da546Spatrick             FindModulesByName(target, arg_cstr, module_list, true);
2313061da546Spatrick         if (num_matches > 0) {
2314061da546Spatrick           for (size_t i = 0; i < num_matches; ++i) {
2315061da546Spatrick             if (m_interpreter.WasInterrupted())
2316061da546Spatrick               break;
2317061da546Spatrick             Module *module = module_list.GetModulePointerAtIndex(i);
2318061da546Spatrick             if (module) {
2319061da546Spatrick               if (DumpModuleSymbolFile(result.GetOutputStream(), module))
2320061da546Spatrick                 num_dumped++;
2321061da546Spatrick             }
2322061da546Spatrick           }
2323061da546Spatrick         } else
2324061da546Spatrick           result.AppendWarningWithFormat(
2325061da546Spatrick               "Unable to find an image that matches '%s'.\n", arg_cstr);
2326061da546Spatrick       }
2327061da546Spatrick     }
2328061da546Spatrick 
2329061da546Spatrick     if (num_dumped > 0)
2330061da546Spatrick       result.SetStatus(eReturnStatusSuccessFinishResult);
2331061da546Spatrick     else {
2332061da546Spatrick       result.AppendError("no matching executable images found");
2333061da546Spatrick     }
2334061da546Spatrick     return result.Succeeded();
2335061da546Spatrick   }
2336061da546Spatrick };
2337061da546Spatrick 
2338061da546Spatrick #pragma mark CommandObjectTargetModulesDumpLineTable
2339061da546Spatrick #define LLDB_OPTIONS_target_modules_dump
2340061da546Spatrick #include "CommandOptions.inc"
2341061da546Spatrick 
2342061da546Spatrick // Image debug line table dumping command
2343061da546Spatrick 
2344061da546Spatrick class CommandObjectTargetModulesDumpLineTable
2345061da546Spatrick     : public CommandObjectTargetModulesSourceFileAutoComplete {
2346061da546Spatrick public:
CommandObjectTargetModulesDumpLineTable(CommandInterpreter & interpreter)2347061da546Spatrick   CommandObjectTargetModulesDumpLineTable(CommandInterpreter &interpreter)
2348061da546Spatrick       : CommandObjectTargetModulesSourceFileAutoComplete(
2349061da546Spatrick             interpreter, "target modules dump line-table",
2350061da546Spatrick             "Dump the line table for one or more compilation units.", nullptr,
2351061da546Spatrick             eCommandRequiresTarget) {}
2352061da546Spatrick 
2353061da546Spatrick   ~CommandObjectTargetModulesDumpLineTable() override = default;
2354061da546Spatrick 
GetOptions()2355061da546Spatrick   Options *GetOptions() override { return &m_options; }
2356061da546Spatrick 
2357061da546Spatrick protected:
DoExecute(Args & command,CommandReturnObject & result)2358061da546Spatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
2359061da546Spatrick     Target *target = m_exe_ctx.GetTargetPtr();
2360061da546Spatrick     uint32_t total_num_dumped = 0;
2361061da546Spatrick 
2362061da546Spatrick     uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
2363061da546Spatrick     result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2364061da546Spatrick     result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2365061da546Spatrick 
2366061da546Spatrick     if (command.GetArgumentCount() == 0) {
2367061da546Spatrick       result.AppendError("file option must be specified.");
2368061da546Spatrick       return result.Succeeded();
2369061da546Spatrick     } else {
2370061da546Spatrick       // Dump specified images (by basename or fullpath)
2371061da546Spatrick       const char *arg_cstr;
2372061da546Spatrick       for (int arg_idx = 0;
2373061da546Spatrick            (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
2374061da546Spatrick            ++arg_idx) {
2375061da546Spatrick         FileSpec file_spec(arg_cstr);
2376061da546Spatrick 
2377061da546Spatrick         const ModuleList &target_modules = target->GetImages();
2378061da546Spatrick         std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
2379be691f3bSpatrick         if (target_modules.GetSize() > 0) {
2380061da546Spatrick           uint32_t num_dumped = 0;
2381be691f3bSpatrick           for (ModuleSP module_sp : target_modules.ModulesNoLocking()) {
2382061da546Spatrick             if (m_interpreter.WasInterrupted())
2383061da546Spatrick               break;
2384061da546Spatrick             if (DumpCompileUnitLineTable(
2385be691f3bSpatrick                     m_interpreter, result.GetOutputStream(), module_sp.get(),
2386061da546Spatrick                     file_spec,
2387061da546Spatrick                     m_options.m_verbose ? eDescriptionLevelFull
2388061da546Spatrick                                         : eDescriptionLevelBrief))
2389061da546Spatrick               num_dumped++;
2390061da546Spatrick           }
2391061da546Spatrick           if (num_dumped == 0)
2392061da546Spatrick             result.AppendWarningWithFormat(
2393061da546Spatrick                 "No source filenames matched '%s'.\n", arg_cstr);
2394061da546Spatrick           else
2395061da546Spatrick             total_num_dumped += num_dumped;
2396061da546Spatrick         }
2397061da546Spatrick       }
2398061da546Spatrick     }
2399061da546Spatrick 
2400061da546Spatrick     if (total_num_dumped > 0)
2401061da546Spatrick       result.SetStatus(eReturnStatusSuccessFinishResult);
2402061da546Spatrick     else {
2403061da546Spatrick       result.AppendError("no source filenames matched any command arguments");
2404061da546Spatrick     }
2405061da546Spatrick     return result.Succeeded();
2406061da546Spatrick   }
2407061da546Spatrick 
2408061da546Spatrick   class CommandOptions : public Options {
2409061da546Spatrick   public:
CommandOptions()2410*f6aab3d8Srobert     CommandOptions() { OptionParsingStarting(nullptr); }
2411061da546Spatrick 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)2412061da546Spatrick     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2413061da546Spatrick                           ExecutionContext *execution_context) override {
2414061da546Spatrick       assert(option_idx == 0 && "We only have one option.");
2415061da546Spatrick       m_verbose = true;
2416061da546Spatrick 
2417061da546Spatrick       return Status();
2418061da546Spatrick     }
2419061da546Spatrick 
OptionParsingStarting(ExecutionContext * execution_context)2420061da546Spatrick     void OptionParsingStarting(ExecutionContext *execution_context) override {
2421061da546Spatrick       m_verbose = false;
2422061da546Spatrick     }
2423061da546Spatrick 
GetDefinitions()2424061da546Spatrick     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2425*f6aab3d8Srobert       return llvm::ArrayRef(g_target_modules_dump_options);
2426061da546Spatrick     }
2427061da546Spatrick 
2428061da546Spatrick     bool m_verbose;
2429061da546Spatrick   };
2430061da546Spatrick 
2431061da546Spatrick   CommandOptions m_options;
2432061da546Spatrick };
2433061da546Spatrick 
2434061da546Spatrick #pragma mark CommandObjectTargetModulesDump
2435061da546Spatrick 
2436061da546Spatrick // Dump multi-word command for target modules
2437061da546Spatrick 
2438061da546Spatrick class CommandObjectTargetModulesDump : public CommandObjectMultiword {
2439061da546Spatrick public:
2440061da546Spatrick   // Constructors and Destructors
CommandObjectTargetModulesDump(CommandInterpreter & interpreter)2441061da546Spatrick   CommandObjectTargetModulesDump(CommandInterpreter &interpreter)
2442061da546Spatrick       : CommandObjectMultiword(
2443061da546Spatrick             interpreter, "target modules dump",
2444*f6aab3d8Srobert             "Commands for dumping information about one or more target "
2445*f6aab3d8Srobert             "modules.",
2446061da546Spatrick             "target modules dump "
2447*f6aab3d8Srobert             "[objfile|symtab|sections|ast|symfile|line-table|pcm-info] "
2448061da546Spatrick             "[<file1> <file2> ...]") {
2449061da546Spatrick     LoadSubCommand("objfile",
2450061da546Spatrick                    CommandObjectSP(
2451061da546Spatrick                        new CommandObjectTargetModulesDumpObjfile(interpreter)));
2452061da546Spatrick     LoadSubCommand(
2453061da546Spatrick         "symtab",
2454061da546Spatrick         CommandObjectSP(new CommandObjectTargetModulesDumpSymtab(interpreter)));
2455061da546Spatrick     LoadSubCommand("sections",
2456061da546Spatrick                    CommandObjectSP(new CommandObjectTargetModulesDumpSections(
2457061da546Spatrick                        interpreter)));
2458061da546Spatrick     LoadSubCommand("symfile",
2459061da546Spatrick                    CommandObjectSP(
2460061da546Spatrick                        new CommandObjectTargetModulesDumpSymfile(interpreter)));
2461061da546Spatrick     LoadSubCommand(
2462061da546Spatrick         "ast", CommandObjectSP(
2463061da546Spatrick                    new CommandObjectTargetModulesDumpClangAST(interpreter)));
2464061da546Spatrick     LoadSubCommand("line-table",
2465061da546Spatrick                    CommandObjectSP(new CommandObjectTargetModulesDumpLineTable(
2466061da546Spatrick                        interpreter)));
2467*f6aab3d8Srobert     LoadSubCommand(
2468*f6aab3d8Srobert         "pcm-info",
2469*f6aab3d8Srobert         CommandObjectSP(
2470*f6aab3d8Srobert             new CommandObjectTargetModulesDumpClangPCMInfo(interpreter)));
2471061da546Spatrick   }
2472061da546Spatrick 
2473061da546Spatrick   ~CommandObjectTargetModulesDump() override = default;
2474061da546Spatrick };
2475061da546Spatrick 
2476061da546Spatrick class CommandObjectTargetModulesAdd : public CommandObjectParsed {
2477061da546Spatrick public:
CommandObjectTargetModulesAdd(CommandInterpreter & interpreter)2478061da546Spatrick   CommandObjectTargetModulesAdd(CommandInterpreter &interpreter)
2479061da546Spatrick       : CommandObjectParsed(interpreter, "target modules add",
2480061da546Spatrick                             "Add a new module to the current target's modules.",
2481061da546Spatrick                             "target modules add [<module>]",
2482061da546Spatrick                             eCommandRequiresTarget),
2483*f6aab3d8Srobert         m_symbol_file(LLDB_OPT_SET_1, false, "symfile", 's', 0,
2484*f6aab3d8Srobert                       eArgTypeFilename,
2485061da546Spatrick                       "Fullpath to a stand alone debug "
2486061da546Spatrick                       "symbols file for when debug symbols "
2487061da546Spatrick                       "are not in the executable.") {
2488061da546Spatrick     m_option_group.Append(&m_uuid_option_group, LLDB_OPT_SET_ALL,
2489061da546Spatrick                           LLDB_OPT_SET_1);
2490061da546Spatrick     m_option_group.Append(&m_symbol_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2491061da546Spatrick     m_option_group.Finalize();
2492*f6aab3d8Srobert     CommandArgumentData module_arg{eArgTypePath, eArgRepeatStar};
2493*f6aab3d8Srobert     m_arguments.push_back({module_arg});
2494061da546Spatrick   }
2495061da546Spatrick 
2496061da546Spatrick   ~CommandObjectTargetModulesAdd() override = default;
2497061da546Spatrick 
GetOptions()2498061da546Spatrick   Options *GetOptions() override { return &m_option_group; }
2499061da546Spatrick 
2500061da546Spatrick   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)2501061da546Spatrick   HandleArgumentCompletion(CompletionRequest &request,
2502061da546Spatrick                            OptionElementVector &opt_element_vector) override {
2503061da546Spatrick     CommandCompletions::InvokeCommonCompletionCallbacks(
2504061da546Spatrick         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
2505061da546Spatrick         request, nullptr);
2506061da546Spatrick   }
2507061da546Spatrick 
2508061da546Spatrick protected:
2509061da546Spatrick   OptionGroupOptions m_option_group;
2510061da546Spatrick   OptionGroupUUID m_uuid_option_group;
2511061da546Spatrick   OptionGroupFile m_symbol_file;
2512061da546Spatrick 
DoExecute(Args & args,CommandReturnObject & result)2513061da546Spatrick   bool DoExecute(Args &args, CommandReturnObject &result) override {
2514061da546Spatrick     Target *target = &GetSelectedTarget();
2515061da546Spatrick     bool flush = false;
2516061da546Spatrick 
2517061da546Spatrick     const size_t argc = args.GetArgumentCount();
2518061da546Spatrick     if (argc == 0) {
2519061da546Spatrick       if (m_uuid_option_group.GetOptionValue().OptionWasSet()) {
2520061da546Spatrick         // We are given a UUID only, go locate the file
2521061da546Spatrick         ModuleSpec module_spec;
2522061da546Spatrick         module_spec.GetUUID() =
2523061da546Spatrick             m_uuid_option_group.GetOptionValue().GetCurrentValue();
2524061da546Spatrick         if (m_symbol_file.GetOptionValue().OptionWasSet())
2525061da546Spatrick           module_spec.GetSymbolFileSpec() =
2526061da546Spatrick               m_symbol_file.GetOptionValue().GetCurrentValue();
2527*f6aab3d8Srobert         Status error;
2528*f6aab3d8Srobert         if (Symbols::DownloadObjectAndSymbolFile(module_spec, error)) {
2529061da546Spatrick           ModuleSP module_sp(
2530061da546Spatrick               target->GetOrCreateModule(module_spec, true /* notify */));
2531061da546Spatrick           if (module_sp) {
2532061da546Spatrick             result.SetStatus(eReturnStatusSuccessFinishResult);
2533061da546Spatrick             return true;
2534061da546Spatrick           } else {
2535061da546Spatrick             StreamString strm;
2536061da546Spatrick             module_spec.GetUUID().Dump(&strm);
2537061da546Spatrick             if (module_spec.GetFileSpec()) {
2538061da546Spatrick               if (module_spec.GetSymbolFileSpec()) {
2539061da546Spatrick                 result.AppendErrorWithFormat(
2540061da546Spatrick                     "Unable to create the executable or symbol file with "
2541061da546Spatrick                     "UUID %s with path %s and symbol file %s",
2542061da546Spatrick                     strm.GetData(), module_spec.GetFileSpec().GetPath().c_str(),
2543061da546Spatrick                     module_spec.GetSymbolFileSpec().GetPath().c_str());
2544061da546Spatrick               } else {
2545061da546Spatrick                 result.AppendErrorWithFormat(
2546061da546Spatrick                     "Unable to create the executable or symbol file with "
2547061da546Spatrick                     "UUID %s with path %s",
2548061da546Spatrick                     strm.GetData(),
2549061da546Spatrick                     module_spec.GetFileSpec().GetPath().c_str());
2550061da546Spatrick               }
2551061da546Spatrick             } else {
2552061da546Spatrick               result.AppendErrorWithFormat("Unable to create the executable "
2553061da546Spatrick                                            "or symbol file with UUID %s",
2554061da546Spatrick                                            strm.GetData());
2555061da546Spatrick             }
2556061da546Spatrick             return false;
2557061da546Spatrick           }
2558061da546Spatrick         } else {
2559061da546Spatrick           StreamString strm;
2560061da546Spatrick           module_spec.GetUUID().Dump(&strm);
2561061da546Spatrick           result.AppendErrorWithFormat(
2562061da546Spatrick               "Unable to locate the executable or symbol file with UUID %s",
2563061da546Spatrick               strm.GetData());
2564*f6aab3d8Srobert           result.SetError(error);
2565061da546Spatrick           return false;
2566061da546Spatrick         }
2567061da546Spatrick       } else {
2568061da546Spatrick         result.AppendError(
2569061da546Spatrick             "one or more executable image paths must be specified");
2570061da546Spatrick         return false;
2571061da546Spatrick       }
2572061da546Spatrick     } else {
2573061da546Spatrick       for (auto &entry : args.entries()) {
2574061da546Spatrick         if (entry.ref().empty())
2575061da546Spatrick           continue;
2576061da546Spatrick 
2577061da546Spatrick         FileSpec file_spec(entry.ref());
2578061da546Spatrick         if (FileSystem::Instance().Exists(file_spec)) {
2579061da546Spatrick           ModuleSpec module_spec(file_spec);
2580061da546Spatrick           if (m_uuid_option_group.GetOptionValue().OptionWasSet())
2581061da546Spatrick             module_spec.GetUUID() =
2582061da546Spatrick                 m_uuid_option_group.GetOptionValue().GetCurrentValue();
2583061da546Spatrick           if (m_symbol_file.GetOptionValue().OptionWasSet())
2584061da546Spatrick             module_spec.GetSymbolFileSpec() =
2585061da546Spatrick                 m_symbol_file.GetOptionValue().GetCurrentValue();
2586061da546Spatrick           if (!module_spec.GetArchitecture().IsValid())
2587061da546Spatrick             module_spec.GetArchitecture() = target->GetArchitecture();
2588061da546Spatrick           Status error;
2589061da546Spatrick           ModuleSP module_sp(target->GetOrCreateModule(
2590061da546Spatrick               module_spec, true /* notify */, &error));
2591061da546Spatrick           if (!module_sp) {
2592061da546Spatrick             const char *error_cstr = error.AsCString();
2593061da546Spatrick             if (error_cstr)
2594061da546Spatrick               result.AppendError(error_cstr);
2595061da546Spatrick             else
2596061da546Spatrick               result.AppendErrorWithFormat("unsupported module: %s",
2597061da546Spatrick                                            entry.c_str());
2598061da546Spatrick             return false;
2599061da546Spatrick           } else {
2600061da546Spatrick             flush = true;
2601061da546Spatrick           }
2602061da546Spatrick           result.SetStatus(eReturnStatusSuccessFinishResult);
2603061da546Spatrick         } else {
2604061da546Spatrick           std::string resolved_path = file_spec.GetPath();
2605061da546Spatrick           if (resolved_path != entry.ref()) {
2606061da546Spatrick             result.AppendErrorWithFormat(
2607061da546Spatrick                 "invalid module path '%s' with resolved path '%s'\n",
2608061da546Spatrick                 entry.ref().str().c_str(), resolved_path.c_str());
2609061da546Spatrick             break;
2610061da546Spatrick           }
2611061da546Spatrick           result.AppendErrorWithFormat("invalid module path '%s'\n",
2612061da546Spatrick                                        entry.c_str());
2613061da546Spatrick           break;
2614061da546Spatrick         }
2615061da546Spatrick       }
2616061da546Spatrick     }
2617061da546Spatrick 
2618061da546Spatrick     if (flush) {
2619061da546Spatrick       ProcessSP process = target->GetProcessSP();
2620061da546Spatrick       if (process)
2621061da546Spatrick         process->Flush();
2622061da546Spatrick     }
2623061da546Spatrick 
2624061da546Spatrick     return result.Succeeded();
2625061da546Spatrick   }
2626061da546Spatrick };
2627061da546Spatrick 
2628061da546Spatrick class CommandObjectTargetModulesLoad
2629061da546Spatrick     : public CommandObjectTargetModulesModuleAutoComplete {
2630061da546Spatrick public:
CommandObjectTargetModulesLoad(CommandInterpreter & interpreter)2631061da546Spatrick   CommandObjectTargetModulesLoad(CommandInterpreter &interpreter)
2632061da546Spatrick       : CommandObjectTargetModulesModuleAutoComplete(
2633061da546Spatrick             interpreter, "target modules load",
2634061da546Spatrick             "Set the load addresses for one or more sections in a target "
2635061da546Spatrick             "module.",
2636061da546Spatrick             "target modules load [--file <module> --uuid <uuid>] <sect-name> "
2637061da546Spatrick             "<address> [<sect-name> <address> ....]",
2638061da546Spatrick             eCommandRequiresTarget),
2639061da546Spatrick         m_file_option(LLDB_OPT_SET_1, false, "file", 'f', 0, eArgTypeName,
2640061da546Spatrick                       "Fullpath or basename for module to load.", ""),
2641061da546Spatrick         m_load_option(LLDB_OPT_SET_1, false, "load", 'l',
2642061da546Spatrick                       "Write file contents to the memory.", false, true),
2643061da546Spatrick         m_pc_option(LLDB_OPT_SET_1, false, "set-pc-to-entry", 'p',
2644061da546Spatrick                     "Set PC to the entry point."
2645061da546Spatrick                     " Only applicable with '--load' option.",
2646061da546Spatrick                     false, true),
2647061da546Spatrick         m_slide_option(LLDB_OPT_SET_1, false, "slide", 's', 0, eArgTypeOffset,
2648061da546Spatrick                        "Set the load address for all sections to be the "
2649061da546Spatrick                        "virtual address in the file plus the offset.",
2650061da546Spatrick                        0) {
2651061da546Spatrick     m_option_group.Append(&m_uuid_option_group, LLDB_OPT_SET_ALL,
2652061da546Spatrick                           LLDB_OPT_SET_1);
2653061da546Spatrick     m_option_group.Append(&m_file_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2654061da546Spatrick     m_option_group.Append(&m_load_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2655061da546Spatrick     m_option_group.Append(&m_pc_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2656061da546Spatrick     m_option_group.Append(&m_slide_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2657061da546Spatrick     m_option_group.Finalize();
2658061da546Spatrick   }
2659061da546Spatrick 
2660061da546Spatrick   ~CommandObjectTargetModulesLoad() override = default;
2661061da546Spatrick 
GetOptions()2662061da546Spatrick   Options *GetOptions() override { return &m_option_group; }
2663061da546Spatrick 
2664061da546Spatrick protected:
DoExecute(Args & args,CommandReturnObject & result)2665061da546Spatrick   bool DoExecute(Args &args, CommandReturnObject &result) override {
2666061da546Spatrick     Target *target = &GetSelectedTarget();
2667061da546Spatrick     const bool load = m_load_option.GetOptionValue().GetCurrentValue();
2668061da546Spatrick     const bool set_pc = m_pc_option.GetOptionValue().GetCurrentValue();
2669061da546Spatrick 
2670061da546Spatrick     const size_t argc = args.GetArgumentCount();
2671061da546Spatrick     ModuleSpec module_spec;
2672061da546Spatrick     bool search_using_module_spec = false;
2673061da546Spatrick 
2674061da546Spatrick     // Allow "load" option to work without --file or --uuid option.
2675061da546Spatrick     if (load) {
2676061da546Spatrick       if (!m_file_option.GetOptionValue().OptionWasSet() &&
2677061da546Spatrick           !m_uuid_option_group.GetOptionValue().OptionWasSet()) {
2678061da546Spatrick         ModuleList &module_list = target->GetImages();
2679061da546Spatrick         if (module_list.GetSize() == 1) {
2680061da546Spatrick           search_using_module_spec = true;
2681061da546Spatrick           module_spec.GetFileSpec() =
2682061da546Spatrick               module_list.GetModuleAtIndex(0)->GetFileSpec();
2683061da546Spatrick         }
2684061da546Spatrick       }
2685061da546Spatrick     }
2686061da546Spatrick 
2687061da546Spatrick     if (m_file_option.GetOptionValue().OptionWasSet()) {
2688061da546Spatrick       search_using_module_spec = true;
2689061da546Spatrick       const char *arg_cstr = m_file_option.GetOptionValue().GetCurrentValue();
2690061da546Spatrick       const bool use_global_module_list = true;
2691061da546Spatrick       ModuleList module_list;
2692061da546Spatrick       const size_t num_matches = FindModulesByName(
2693061da546Spatrick           target, arg_cstr, module_list, use_global_module_list);
2694061da546Spatrick       if (num_matches == 1) {
2695061da546Spatrick         module_spec.GetFileSpec() =
2696061da546Spatrick             module_list.GetModuleAtIndex(0)->GetFileSpec();
2697061da546Spatrick       } else if (num_matches > 1) {
2698061da546Spatrick         search_using_module_spec = false;
2699061da546Spatrick         result.AppendErrorWithFormat(
2700061da546Spatrick             "more than 1 module matched by name '%s'\n", arg_cstr);
2701061da546Spatrick       } else {
2702061da546Spatrick         search_using_module_spec = false;
2703061da546Spatrick         result.AppendErrorWithFormat("no object file for module '%s'\n",
2704061da546Spatrick                                      arg_cstr);
2705061da546Spatrick       }
2706061da546Spatrick     }
2707061da546Spatrick 
2708061da546Spatrick     if (m_uuid_option_group.GetOptionValue().OptionWasSet()) {
2709061da546Spatrick       search_using_module_spec = true;
2710061da546Spatrick       module_spec.GetUUID() =
2711061da546Spatrick           m_uuid_option_group.GetOptionValue().GetCurrentValue();
2712061da546Spatrick     }
2713061da546Spatrick 
2714061da546Spatrick     if (search_using_module_spec) {
2715061da546Spatrick       ModuleList matching_modules;
2716061da546Spatrick       target->GetImages().FindModules(module_spec, matching_modules);
2717061da546Spatrick       const size_t num_matches = matching_modules.GetSize();
2718061da546Spatrick 
2719061da546Spatrick       char path[PATH_MAX];
2720061da546Spatrick       if (num_matches == 1) {
2721061da546Spatrick         Module *module = matching_modules.GetModulePointerAtIndex(0);
2722061da546Spatrick         if (module) {
2723061da546Spatrick           ObjectFile *objfile = module->GetObjectFile();
2724061da546Spatrick           if (objfile) {
2725061da546Spatrick             SectionList *section_list = module->GetSectionList();
2726061da546Spatrick             if (section_list) {
2727061da546Spatrick               bool changed = false;
2728061da546Spatrick               if (argc == 0) {
2729061da546Spatrick                 if (m_slide_option.GetOptionValue().OptionWasSet()) {
2730061da546Spatrick                   const addr_t slide =
2731061da546Spatrick                       m_slide_option.GetOptionValue().GetCurrentValue();
2732061da546Spatrick                   const bool slide_is_offset = true;
2733061da546Spatrick                   module->SetLoadAddress(*target, slide, slide_is_offset,
2734061da546Spatrick                                          changed);
2735061da546Spatrick                 } else {
2736061da546Spatrick                   result.AppendError("one or more section name + load "
2737061da546Spatrick                                      "address pair must be specified");
2738061da546Spatrick                   return false;
2739061da546Spatrick                 }
2740061da546Spatrick               } else {
2741061da546Spatrick                 if (m_slide_option.GetOptionValue().OptionWasSet()) {
2742061da546Spatrick                   result.AppendError("The \"--slide <offset>\" option can't "
2743061da546Spatrick                                      "be used in conjunction with setting "
2744061da546Spatrick                                      "section load addresses.\n");
2745061da546Spatrick                   return false;
2746061da546Spatrick                 }
2747061da546Spatrick 
2748061da546Spatrick                 for (size_t i = 0; i < argc; i += 2) {
2749061da546Spatrick                   const char *sect_name = args.GetArgumentAtIndex(i);
2750061da546Spatrick                   const char *load_addr_cstr = args.GetArgumentAtIndex(i + 1);
2751061da546Spatrick                   if (sect_name && load_addr_cstr) {
2752061da546Spatrick                     ConstString const_sect_name(sect_name);
2753dda28197Spatrick                     addr_t load_addr;
2754dda28197Spatrick                     if (llvm::to_integer(load_addr_cstr, load_addr)) {
2755061da546Spatrick                       SectionSP section_sp(
2756061da546Spatrick                           section_list->FindSectionByName(const_sect_name));
2757061da546Spatrick                       if (section_sp) {
2758061da546Spatrick                         if (section_sp->IsThreadSpecific()) {
2759061da546Spatrick                           result.AppendErrorWithFormat(
2760061da546Spatrick                               "thread specific sections are not yet "
2761061da546Spatrick                               "supported (section '%s')\n",
2762061da546Spatrick                               sect_name);
2763061da546Spatrick                           break;
2764061da546Spatrick                         } else {
2765061da546Spatrick                           if (target->GetSectionLoadList()
2766061da546Spatrick                                   .SetSectionLoadAddress(section_sp, load_addr))
2767061da546Spatrick                             changed = true;
2768061da546Spatrick                           result.AppendMessageWithFormat(
2769061da546Spatrick                               "section '%s' loaded at 0x%" PRIx64 "\n",
2770061da546Spatrick                               sect_name, load_addr);
2771061da546Spatrick                         }
2772061da546Spatrick                       } else {
2773061da546Spatrick                         result.AppendErrorWithFormat("no section found that "
2774061da546Spatrick                                                      "matches the section "
2775061da546Spatrick                                                      "name '%s'\n",
2776061da546Spatrick                                                      sect_name);
2777061da546Spatrick                         break;
2778061da546Spatrick                       }
2779061da546Spatrick                     } else {
2780061da546Spatrick                       result.AppendErrorWithFormat(
2781061da546Spatrick                           "invalid load address string '%s'\n", load_addr_cstr);
2782061da546Spatrick                       break;
2783061da546Spatrick                     }
2784061da546Spatrick                   } else {
2785061da546Spatrick                     if (sect_name)
2786061da546Spatrick                       result.AppendError("section names must be followed by "
2787061da546Spatrick                                          "a load address.\n");
2788061da546Spatrick                     else
2789061da546Spatrick                       result.AppendError("one or more section name + load "
2790061da546Spatrick                                          "address pair must be specified.\n");
2791061da546Spatrick                     break;
2792061da546Spatrick                   }
2793061da546Spatrick                 }
2794061da546Spatrick               }
2795061da546Spatrick 
2796061da546Spatrick               if (changed) {
2797061da546Spatrick                 target->ModulesDidLoad(matching_modules);
2798061da546Spatrick                 Process *process = m_exe_ctx.GetProcessPtr();
2799061da546Spatrick                 if (process)
2800061da546Spatrick                   process->Flush();
2801061da546Spatrick               }
2802061da546Spatrick               if (load) {
2803061da546Spatrick                 ProcessSP process = target->CalculateProcess();
2804061da546Spatrick                 Address file_entry = objfile->GetEntryPointAddress();
2805061da546Spatrick                 if (!process) {
2806061da546Spatrick                   result.AppendError("No process");
2807061da546Spatrick                   return false;
2808061da546Spatrick                 }
2809061da546Spatrick                 if (set_pc && !file_entry.IsValid()) {
2810061da546Spatrick                   result.AppendError("No entry address in object file");
2811061da546Spatrick                   return false;
2812061da546Spatrick                 }
2813061da546Spatrick                 std::vector<ObjectFile::LoadableData> loadables(
2814061da546Spatrick                     objfile->GetLoadableData(*target));
2815061da546Spatrick                 if (loadables.size() == 0) {
2816061da546Spatrick                   result.AppendError("No loadable sections");
2817061da546Spatrick                   return false;
2818061da546Spatrick                 }
2819061da546Spatrick                 Status error = process->WriteObjectFile(std::move(loadables));
2820061da546Spatrick                 if (error.Fail()) {
2821061da546Spatrick                   result.AppendError(error.AsCString());
2822061da546Spatrick                   return false;
2823061da546Spatrick                 }
2824061da546Spatrick                 if (set_pc) {
2825061da546Spatrick                   ThreadList &thread_list = process->GetThreadList();
2826061da546Spatrick                   RegisterContextSP reg_context(
2827061da546Spatrick                       thread_list.GetSelectedThread()->GetRegisterContext());
2828061da546Spatrick                   addr_t file_entry_addr = file_entry.GetLoadAddress(target);
2829061da546Spatrick                   if (!reg_context->SetPC(file_entry_addr)) {
2830061da546Spatrick                     result.AppendErrorWithFormat("failed to set PC value to "
2831061da546Spatrick                                                  "0x%" PRIx64 "\n",
2832061da546Spatrick                                                  file_entry_addr);
2833061da546Spatrick                   }
2834061da546Spatrick                 }
2835061da546Spatrick               }
2836061da546Spatrick             } else {
2837061da546Spatrick               module->GetFileSpec().GetPath(path, sizeof(path));
2838061da546Spatrick               result.AppendErrorWithFormat("no sections in object file '%s'\n",
2839061da546Spatrick                                            path);
2840061da546Spatrick             }
2841061da546Spatrick           } else {
2842061da546Spatrick             module->GetFileSpec().GetPath(path, sizeof(path));
2843061da546Spatrick             result.AppendErrorWithFormat("no object file for module '%s'\n",
2844061da546Spatrick                                          path);
2845061da546Spatrick           }
2846061da546Spatrick         } else {
2847061da546Spatrick           FileSpec *module_spec_file = module_spec.GetFileSpecPtr();
2848061da546Spatrick           if (module_spec_file) {
2849061da546Spatrick             module_spec_file->GetPath(path, sizeof(path));
2850061da546Spatrick             result.AppendErrorWithFormat("invalid module '%s'.\n", path);
2851061da546Spatrick           } else
2852061da546Spatrick             result.AppendError("no module spec");
2853061da546Spatrick         }
2854061da546Spatrick       } else {
2855061da546Spatrick         std::string uuid_str;
2856061da546Spatrick 
2857061da546Spatrick         if (module_spec.GetFileSpec())
2858061da546Spatrick           module_spec.GetFileSpec().GetPath(path, sizeof(path));
2859061da546Spatrick         else
2860061da546Spatrick           path[0] = '\0';
2861061da546Spatrick 
2862061da546Spatrick         if (module_spec.GetUUIDPtr())
2863061da546Spatrick           uuid_str = module_spec.GetUUID().GetAsString();
2864061da546Spatrick         if (num_matches > 1) {
2865061da546Spatrick           result.AppendErrorWithFormat(
2866061da546Spatrick               "multiple modules match%s%s%s%s:\n", path[0] ? " file=" : "",
2867061da546Spatrick               path, !uuid_str.empty() ? " uuid=" : "", uuid_str.c_str());
2868061da546Spatrick           for (size_t i = 0; i < num_matches; ++i) {
2869061da546Spatrick             if (matching_modules.GetModulePointerAtIndex(i)
2870061da546Spatrick                     ->GetFileSpec()
2871061da546Spatrick                     .GetPath(path, sizeof(path)))
2872061da546Spatrick               result.AppendMessageWithFormat("%s\n", path);
2873061da546Spatrick           }
2874061da546Spatrick         } else {
2875061da546Spatrick           result.AppendErrorWithFormat(
2876061da546Spatrick               "no modules were found  that match%s%s%s%s.\n",
2877061da546Spatrick               path[0] ? " file=" : "", path, !uuid_str.empty() ? " uuid=" : "",
2878061da546Spatrick               uuid_str.c_str());
2879061da546Spatrick         }
2880061da546Spatrick       }
2881061da546Spatrick     } else {
2882061da546Spatrick       result.AppendError("either the \"--file <module>\" or the \"--uuid "
2883061da546Spatrick                          "<uuid>\" option must be specified.\n");
2884061da546Spatrick       return false;
2885061da546Spatrick     }
2886061da546Spatrick     return result.Succeeded();
2887061da546Spatrick   }
2888061da546Spatrick 
2889061da546Spatrick   OptionGroupOptions m_option_group;
2890061da546Spatrick   OptionGroupUUID m_uuid_option_group;
2891061da546Spatrick   OptionGroupString m_file_option;
2892061da546Spatrick   OptionGroupBoolean m_load_option;
2893061da546Spatrick   OptionGroupBoolean m_pc_option;
2894061da546Spatrick   OptionGroupUInt64 m_slide_option;
2895061da546Spatrick };
2896061da546Spatrick 
2897*f6aab3d8Srobert #pragma mark CommandObjectTargetModulesList
2898061da546Spatrick // List images with associated information
2899061da546Spatrick #define LLDB_OPTIONS_target_modules_list
2900061da546Spatrick #include "CommandOptions.inc"
2901061da546Spatrick 
2902061da546Spatrick class CommandObjectTargetModulesList : public CommandObjectParsed {
2903061da546Spatrick public:
2904061da546Spatrick   class CommandOptions : public Options {
2905061da546Spatrick   public:
2906*f6aab3d8Srobert     CommandOptions() = default;
2907061da546Spatrick 
2908061da546Spatrick     ~CommandOptions() override = default;
2909061da546Spatrick 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)2910061da546Spatrick     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2911061da546Spatrick                           ExecutionContext *execution_context) override {
2912061da546Spatrick       Status error;
2913061da546Spatrick 
2914061da546Spatrick       const int short_option = m_getopt_table[option_idx].val;
2915061da546Spatrick       if (short_option == 'g') {
2916061da546Spatrick         m_use_global_module_list = true;
2917061da546Spatrick       } else if (short_option == 'a') {
2918061da546Spatrick         m_module_addr = OptionArgParser::ToAddress(
2919061da546Spatrick             execution_context, option_arg, LLDB_INVALID_ADDRESS, &error);
2920061da546Spatrick       } else {
2921061da546Spatrick         unsigned long width = 0;
2922061da546Spatrick         option_arg.getAsInteger(0, width);
2923061da546Spatrick         m_format_array.push_back(std::make_pair(short_option, width));
2924061da546Spatrick       }
2925061da546Spatrick       return error;
2926061da546Spatrick     }
2927061da546Spatrick 
OptionParsingStarting(ExecutionContext * execution_context)2928061da546Spatrick     void OptionParsingStarting(ExecutionContext *execution_context) override {
2929061da546Spatrick       m_format_array.clear();
2930061da546Spatrick       m_use_global_module_list = false;
2931061da546Spatrick       m_module_addr = LLDB_INVALID_ADDRESS;
2932061da546Spatrick     }
2933061da546Spatrick 
GetDefinitions()2934061da546Spatrick     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2935*f6aab3d8Srobert       return llvm::ArrayRef(g_target_modules_list_options);
2936061da546Spatrick     }
2937061da546Spatrick 
2938061da546Spatrick     // Instance variables to hold the values for command options.
2939061da546Spatrick     typedef std::vector<std::pair<char, uint32_t>> FormatWidthCollection;
2940061da546Spatrick     FormatWidthCollection m_format_array;
2941be691f3bSpatrick     bool m_use_global_module_list = false;
2942be691f3bSpatrick     lldb::addr_t m_module_addr = LLDB_INVALID_ADDRESS;
2943061da546Spatrick   };
2944061da546Spatrick 
CommandObjectTargetModulesList(CommandInterpreter & interpreter)2945061da546Spatrick   CommandObjectTargetModulesList(CommandInterpreter &interpreter)
2946061da546Spatrick       : CommandObjectParsed(
2947061da546Spatrick             interpreter, "target modules list",
2948*f6aab3d8Srobert             "List current executable and dependent shared library images.") {
2949*f6aab3d8Srobert     CommandArgumentData module_arg{eArgTypeShlibName, eArgRepeatStar};
2950*f6aab3d8Srobert     m_arguments.push_back({module_arg});
2951*f6aab3d8Srobert   }
2952061da546Spatrick 
2953061da546Spatrick   ~CommandObjectTargetModulesList() override = default;
2954061da546Spatrick 
GetOptions()2955061da546Spatrick   Options *GetOptions() override { return &m_options; }
2956061da546Spatrick 
2957061da546Spatrick protected:
DoExecute(Args & command,CommandReturnObject & result)2958061da546Spatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
2959061da546Spatrick     Target *target = GetDebugger().GetSelectedTarget().get();
2960061da546Spatrick     const bool use_global_module_list = m_options.m_use_global_module_list;
2961061da546Spatrick     // Define a local module list here to ensure it lives longer than any
2962061da546Spatrick     // "locker" object which might lock its contents below (through the
2963061da546Spatrick     // "module_list_ptr" variable).
2964061da546Spatrick     ModuleList module_list;
2965061da546Spatrick     if (target == nullptr && !use_global_module_list) {
2966061da546Spatrick       result.AppendError("invalid target, create a debug target using the "
2967061da546Spatrick                          "'target create' command");
2968061da546Spatrick       return false;
2969061da546Spatrick     } else {
2970061da546Spatrick       if (target) {
2971061da546Spatrick         uint32_t addr_byte_size =
2972061da546Spatrick             target->GetArchitecture().GetAddressByteSize();
2973061da546Spatrick         result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2974061da546Spatrick         result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2975061da546Spatrick       }
2976061da546Spatrick       // Dump all sections for all modules images
2977061da546Spatrick       Stream &strm = result.GetOutputStream();
2978061da546Spatrick 
2979061da546Spatrick       if (m_options.m_module_addr != LLDB_INVALID_ADDRESS) {
2980061da546Spatrick         if (target) {
2981061da546Spatrick           Address module_address;
2982061da546Spatrick           if (module_address.SetLoadAddress(m_options.m_module_addr, target)) {
2983061da546Spatrick             ModuleSP module_sp(module_address.GetModule());
2984061da546Spatrick             if (module_sp) {
2985061da546Spatrick               PrintModule(target, module_sp.get(), 0, strm);
2986061da546Spatrick               result.SetStatus(eReturnStatusSuccessFinishResult);
2987061da546Spatrick             } else {
2988061da546Spatrick               result.AppendErrorWithFormat(
2989061da546Spatrick                   "Couldn't find module matching address: 0x%" PRIx64 ".",
2990061da546Spatrick                   m_options.m_module_addr);
2991061da546Spatrick             }
2992061da546Spatrick           } else {
2993061da546Spatrick             result.AppendErrorWithFormat(
2994061da546Spatrick                 "Couldn't find module containing address: 0x%" PRIx64 ".",
2995061da546Spatrick                 m_options.m_module_addr);
2996061da546Spatrick           }
2997061da546Spatrick         } else {
2998061da546Spatrick           result.AppendError(
2999061da546Spatrick               "Can only look up modules by address with a valid target.");
3000061da546Spatrick         }
3001061da546Spatrick         return result.Succeeded();
3002061da546Spatrick       }
3003061da546Spatrick 
3004061da546Spatrick       size_t num_modules = 0;
3005061da546Spatrick 
3006061da546Spatrick       // This locker will be locked on the mutex in module_list_ptr if it is
3007061da546Spatrick       // non-nullptr. Otherwise it will lock the
3008061da546Spatrick       // AllocationModuleCollectionMutex when accessing the global module list
3009061da546Spatrick       // directly.
3010061da546Spatrick       std::unique_lock<std::recursive_mutex> guard(
3011061da546Spatrick           Module::GetAllocationModuleCollectionMutex(), std::defer_lock);
3012061da546Spatrick 
3013061da546Spatrick       const ModuleList *module_list_ptr = nullptr;
3014061da546Spatrick       const size_t argc = command.GetArgumentCount();
3015061da546Spatrick       if (argc == 0) {
3016061da546Spatrick         if (use_global_module_list) {
3017061da546Spatrick           guard.lock();
3018061da546Spatrick           num_modules = Module::GetNumberAllocatedModules();
3019061da546Spatrick         } else {
3020061da546Spatrick           module_list_ptr = &target->GetImages();
3021061da546Spatrick         }
3022061da546Spatrick       } else {
3023dda28197Spatrick         for (const Args::ArgEntry &arg : command) {
3024061da546Spatrick           // Dump specified images (by basename or fullpath)
3025061da546Spatrick           const size_t num_matches = FindModulesByName(
3026dda28197Spatrick               target, arg.c_str(), module_list, use_global_module_list);
3027061da546Spatrick           if (num_matches == 0) {
3028061da546Spatrick             if (argc == 1) {
3029061da546Spatrick               result.AppendErrorWithFormat("no modules found that match '%s'",
3030dda28197Spatrick                                            arg.c_str());
3031061da546Spatrick               return false;
3032061da546Spatrick             }
3033061da546Spatrick           }
3034061da546Spatrick         }
3035061da546Spatrick 
3036061da546Spatrick         module_list_ptr = &module_list;
3037061da546Spatrick       }
3038061da546Spatrick 
3039061da546Spatrick       std::unique_lock<std::recursive_mutex> lock;
3040061da546Spatrick       if (module_list_ptr != nullptr) {
3041061da546Spatrick         lock =
3042061da546Spatrick             std::unique_lock<std::recursive_mutex>(module_list_ptr->GetMutex());
3043061da546Spatrick 
3044061da546Spatrick         num_modules = module_list_ptr->GetSize();
3045061da546Spatrick       }
3046061da546Spatrick 
3047061da546Spatrick       if (num_modules > 0) {
3048061da546Spatrick         for (uint32_t image_idx = 0; image_idx < num_modules; ++image_idx) {
3049061da546Spatrick           ModuleSP module_sp;
3050061da546Spatrick           Module *module;
3051061da546Spatrick           if (module_list_ptr) {
3052061da546Spatrick             module_sp = module_list_ptr->GetModuleAtIndexUnlocked(image_idx);
3053061da546Spatrick             module = module_sp.get();
3054061da546Spatrick           } else {
3055061da546Spatrick             module = Module::GetAllocatedModuleAtIndex(image_idx);
3056061da546Spatrick             module_sp = module->shared_from_this();
3057061da546Spatrick           }
3058061da546Spatrick 
3059061da546Spatrick           const size_t indent = strm.Printf("[%3u] ", image_idx);
3060061da546Spatrick           PrintModule(target, module, indent, strm);
3061061da546Spatrick         }
3062061da546Spatrick         result.SetStatus(eReturnStatusSuccessFinishResult);
3063061da546Spatrick       } else {
3064061da546Spatrick         if (argc) {
3065061da546Spatrick           if (use_global_module_list)
3066061da546Spatrick             result.AppendError(
3067061da546Spatrick                 "the global module list has no matching modules");
3068061da546Spatrick           else
3069061da546Spatrick             result.AppendError("the target has no matching modules");
3070061da546Spatrick         } else {
3071061da546Spatrick           if (use_global_module_list)
3072061da546Spatrick             result.AppendError("the global module list is empty");
3073061da546Spatrick           else
3074061da546Spatrick             result.AppendError(
3075061da546Spatrick                 "the target has no associated executable images");
3076061da546Spatrick         }
3077061da546Spatrick         return false;
3078061da546Spatrick       }
3079061da546Spatrick     }
3080061da546Spatrick     return result.Succeeded();
3081061da546Spatrick   }
3082061da546Spatrick 
PrintModule(Target * target,Module * module,int indent,Stream & strm)3083061da546Spatrick   void PrintModule(Target *target, Module *module, int indent, Stream &strm) {
3084061da546Spatrick     if (module == nullptr) {
3085061da546Spatrick       strm.PutCString("Null module");
3086061da546Spatrick       return;
3087061da546Spatrick     }
3088061da546Spatrick 
3089061da546Spatrick     bool dump_object_name = false;
3090061da546Spatrick     if (m_options.m_format_array.empty()) {
3091061da546Spatrick       m_options.m_format_array.push_back(std::make_pair('u', 0));
3092061da546Spatrick       m_options.m_format_array.push_back(std::make_pair('h', 0));
3093061da546Spatrick       m_options.m_format_array.push_back(std::make_pair('f', 0));
3094061da546Spatrick       m_options.m_format_array.push_back(std::make_pair('S', 0));
3095061da546Spatrick     }
3096061da546Spatrick     const size_t num_entries = m_options.m_format_array.size();
3097061da546Spatrick     bool print_space = false;
3098061da546Spatrick     for (size_t i = 0; i < num_entries; ++i) {
3099061da546Spatrick       if (print_space)
3100061da546Spatrick         strm.PutChar(' ');
3101061da546Spatrick       print_space = true;
3102061da546Spatrick       const char format_char = m_options.m_format_array[i].first;
3103061da546Spatrick       uint32_t width = m_options.m_format_array[i].second;
3104061da546Spatrick       switch (format_char) {
3105061da546Spatrick       case 'A':
3106061da546Spatrick         DumpModuleArchitecture(strm, module, false, width);
3107061da546Spatrick         break;
3108061da546Spatrick 
3109061da546Spatrick       case 't':
3110061da546Spatrick         DumpModuleArchitecture(strm, module, true, width);
3111061da546Spatrick         break;
3112061da546Spatrick 
3113061da546Spatrick       case 'f':
3114061da546Spatrick         DumpFullpath(strm, &module->GetFileSpec(), width);
3115061da546Spatrick         dump_object_name = true;
3116061da546Spatrick         break;
3117061da546Spatrick 
3118061da546Spatrick       case 'd':
3119061da546Spatrick         DumpDirectory(strm, &module->GetFileSpec(), width);
3120061da546Spatrick         break;
3121061da546Spatrick 
3122061da546Spatrick       case 'b':
3123061da546Spatrick         DumpBasename(strm, &module->GetFileSpec(), width);
3124061da546Spatrick         dump_object_name = true;
3125061da546Spatrick         break;
3126061da546Spatrick 
3127061da546Spatrick       case 'h':
3128061da546Spatrick       case 'o':
3129061da546Spatrick         // Image header address
3130061da546Spatrick         {
3131061da546Spatrick           uint32_t addr_nibble_width =
3132061da546Spatrick               target ? (target->GetArchitecture().GetAddressByteSize() * 2)
3133061da546Spatrick                      : 16;
3134061da546Spatrick 
3135061da546Spatrick           ObjectFile *objfile = module->GetObjectFile();
3136061da546Spatrick           if (objfile) {
3137061da546Spatrick             Address base_addr(objfile->GetBaseAddress());
3138061da546Spatrick             if (base_addr.IsValid()) {
3139061da546Spatrick               if (target && !target->GetSectionLoadList().IsEmpty()) {
3140061da546Spatrick                 lldb::addr_t load_addr = base_addr.GetLoadAddress(target);
3141061da546Spatrick                 if (load_addr == LLDB_INVALID_ADDRESS) {
3142061da546Spatrick                   base_addr.Dump(&strm, target,
3143061da546Spatrick                                  Address::DumpStyleModuleWithFileAddress,
3144061da546Spatrick                                  Address::DumpStyleFileAddress);
3145061da546Spatrick                 } else {
3146061da546Spatrick                   if (format_char == 'o') {
3147061da546Spatrick                     // Show the offset of slide for the image
3148061da546Spatrick                     strm.Printf("0x%*.*" PRIx64, addr_nibble_width,
3149061da546Spatrick                                 addr_nibble_width,
3150061da546Spatrick                                 load_addr - base_addr.GetFileAddress());
3151061da546Spatrick                   } else {
3152061da546Spatrick                     // Show the load address of the image
3153061da546Spatrick                     strm.Printf("0x%*.*" PRIx64, addr_nibble_width,
3154061da546Spatrick                                 addr_nibble_width, load_addr);
3155061da546Spatrick                   }
3156061da546Spatrick                 }
3157061da546Spatrick                 break;
3158061da546Spatrick               }
3159061da546Spatrick               // The address was valid, but the image isn't loaded, output the
3160061da546Spatrick               // address in an appropriate format
3161061da546Spatrick               base_addr.Dump(&strm, target, Address::DumpStyleFileAddress);
3162061da546Spatrick               break;
3163061da546Spatrick             }
3164061da546Spatrick           }
3165061da546Spatrick           strm.Printf("%*s", addr_nibble_width + 2, "");
3166061da546Spatrick         }
3167061da546Spatrick         break;
3168061da546Spatrick 
3169061da546Spatrick       case 'r': {
3170061da546Spatrick         size_t ref_count = 0;
3171061da546Spatrick         ModuleSP module_sp(module->shared_from_this());
3172061da546Spatrick         if (module_sp) {
3173061da546Spatrick           // Take one away to make sure we don't count our local "module_sp"
3174061da546Spatrick           ref_count = module_sp.use_count() - 1;
3175061da546Spatrick         }
3176061da546Spatrick         if (width)
3177061da546Spatrick           strm.Printf("{%*" PRIu64 "}", width, (uint64_t)ref_count);
3178061da546Spatrick         else
3179061da546Spatrick           strm.Printf("{%" PRIu64 "}", (uint64_t)ref_count);
3180061da546Spatrick       } break;
3181061da546Spatrick 
3182061da546Spatrick       case 's':
3183061da546Spatrick       case 'S': {
3184061da546Spatrick         if (const SymbolFile *symbol_file = module->GetSymbolFile()) {
3185061da546Spatrick           const FileSpec symfile_spec =
3186061da546Spatrick               symbol_file->GetObjectFile()->GetFileSpec();
3187061da546Spatrick           if (format_char == 'S') {
3188061da546Spatrick             // Dump symbol file only if different from module file
3189061da546Spatrick             if (!symfile_spec || symfile_spec == module->GetFileSpec()) {
3190061da546Spatrick               print_space = false;
3191061da546Spatrick               break;
3192061da546Spatrick             }
3193061da546Spatrick             // Add a newline and indent past the index
3194061da546Spatrick             strm.Printf("\n%*s", indent, "");
3195061da546Spatrick           }
3196061da546Spatrick           DumpFullpath(strm, &symfile_spec, width);
3197061da546Spatrick           dump_object_name = true;
3198061da546Spatrick           break;
3199061da546Spatrick         }
3200061da546Spatrick         strm.Printf("%.*s", width, "<NONE>");
3201061da546Spatrick       } break;
3202061da546Spatrick 
3203061da546Spatrick       case 'm':
3204061da546Spatrick         strm.Format("{0:%c}", llvm::fmt_align(module->GetModificationTime(),
3205061da546Spatrick                                               llvm::AlignStyle::Left, width));
3206061da546Spatrick         break;
3207061da546Spatrick 
3208061da546Spatrick       case 'p':
3209061da546Spatrick         strm.Printf("%p", static_cast<void *>(module));
3210061da546Spatrick         break;
3211061da546Spatrick 
3212061da546Spatrick       case 'u':
3213061da546Spatrick         DumpModuleUUID(strm, module);
3214061da546Spatrick         break;
3215061da546Spatrick 
3216061da546Spatrick       default:
3217061da546Spatrick         break;
3218061da546Spatrick       }
3219061da546Spatrick     }
3220061da546Spatrick     if (dump_object_name) {
3221061da546Spatrick       const char *object_name = module->GetObjectName().GetCString();
3222061da546Spatrick       if (object_name)
3223061da546Spatrick         strm.Printf("(%s)", object_name);
3224061da546Spatrick     }
3225061da546Spatrick     strm.EOL();
3226061da546Spatrick   }
3227061da546Spatrick 
3228061da546Spatrick   CommandOptions m_options;
3229061da546Spatrick };
3230061da546Spatrick 
3231061da546Spatrick #pragma mark CommandObjectTargetModulesShowUnwind
3232061da546Spatrick 
3233061da546Spatrick // Lookup unwind information in images
3234061da546Spatrick #define LLDB_OPTIONS_target_modules_show_unwind
3235061da546Spatrick #include "CommandOptions.inc"
3236061da546Spatrick 
3237061da546Spatrick class CommandObjectTargetModulesShowUnwind : public CommandObjectParsed {
3238061da546Spatrick public:
3239061da546Spatrick   enum {
3240061da546Spatrick     eLookupTypeInvalid = -1,
3241061da546Spatrick     eLookupTypeAddress = 0,
3242061da546Spatrick     eLookupTypeSymbol,
3243061da546Spatrick     eLookupTypeFunction,
3244061da546Spatrick     eLookupTypeFunctionOrSymbol,
3245061da546Spatrick     kNumLookupTypes
3246061da546Spatrick   };
3247061da546Spatrick 
3248061da546Spatrick   class CommandOptions : public Options {
3249061da546Spatrick   public:
3250*f6aab3d8Srobert     CommandOptions() = default;
3251061da546Spatrick 
3252061da546Spatrick     ~CommandOptions() override = default;
3253061da546Spatrick 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)3254061da546Spatrick     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
3255061da546Spatrick                           ExecutionContext *execution_context) override {
3256061da546Spatrick       Status error;
3257061da546Spatrick 
3258061da546Spatrick       const int short_option = m_getopt_table[option_idx].val;
3259061da546Spatrick 
3260061da546Spatrick       switch (short_option) {
3261061da546Spatrick       case 'a': {
3262dda28197Spatrick         m_str = std::string(option_arg);
3263061da546Spatrick         m_type = eLookupTypeAddress;
3264061da546Spatrick         m_addr = OptionArgParser::ToAddress(execution_context, option_arg,
3265061da546Spatrick                                             LLDB_INVALID_ADDRESS, &error);
3266061da546Spatrick         if (m_addr == LLDB_INVALID_ADDRESS)
3267061da546Spatrick           error.SetErrorStringWithFormat("invalid address string '%s'",
3268061da546Spatrick                                          option_arg.str().c_str());
3269061da546Spatrick         break;
3270061da546Spatrick       }
3271061da546Spatrick 
3272061da546Spatrick       case 'n':
3273dda28197Spatrick         m_str = std::string(option_arg);
3274061da546Spatrick         m_type = eLookupTypeFunctionOrSymbol;
3275061da546Spatrick         break;
3276061da546Spatrick 
3277061da546Spatrick       default:
3278061da546Spatrick         llvm_unreachable("Unimplemented option");
3279061da546Spatrick       }
3280061da546Spatrick 
3281061da546Spatrick       return error;
3282061da546Spatrick     }
3283061da546Spatrick 
OptionParsingStarting(ExecutionContext * execution_context)3284061da546Spatrick     void OptionParsingStarting(ExecutionContext *execution_context) override {
3285061da546Spatrick       m_type = eLookupTypeInvalid;
3286061da546Spatrick       m_str.clear();
3287061da546Spatrick       m_addr = LLDB_INVALID_ADDRESS;
3288061da546Spatrick     }
3289061da546Spatrick 
GetDefinitions()3290061da546Spatrick     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
3291*f6aab3d8Srobert       return llvm::ArrayRef(g_target_modules_show_unwind_options);
3292061da546Spatrick     }
3293061da546Spatrick 
3294061da546Spatrick     // Instance variables to hold the values for command options.
3295061da546Spatrick 
3296be691f3bSpatrick     int m_type = eLookupTypeInvalid; // Should be a eLookupTypeXXX enum after
3297be691f3bSpatrick                                      // parsing options
3298061da546Spatrick     std::string m_str; // Holds name lookup
3299be691f3bSpatrick     lldb::addr_t m_addr = LLDB_INVALID_ADDRESS; // Holds the address to lookup
3300061da546Spatrick   };
3301061da546Spatrick 
CommandObjectTargetModulesShowUnwind(CommandInterpreter & interpreter)3302061da546Spatrick   CommandObjectTargetModulesShowUnwind(CommandInterpreter &interpreter)
3303061da546Spatrick       : CommandObjectParsed(
3304061da546Spatrick             interpreter, "target modules show-unwind",
3305061da546Spatrick             "Show synthesized unwind instructions for a function.", nullptr,
3306061da546Spatrick             eCommandRequiresTarget | eCommandRequiresProcess |
3307*f6aab3d8Srobert                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {}
3308061da546Spatrick 
3309061da546Spatrick   ~CommandObjectTargetModulesShowUnwind() override = default;
3310061da546Spatrick 
GetOptions()3311061da546Spatrick   Options *GetOptions() override { return &m_options; }
3312061da546Spatrick 
3313061da546Spatrick protected:
DoExecute(Args & command,CommandReturnObject & result)3314061da546Spatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
3315061da546Spatrick     Target *target = m_exe_ctx.GetTargetPtr();
3316061da546Spatrick     Process *process = m_exe_ctx.GetProcessPtr();
3317061da546Spatrick     ABI *abi = nullptr;
3318061da546Spatrick     if (process)
3319061da546Spatrick       abi = process->GetABI().get();
3320061da546Spatrick 
3321061da546Spatrick     if (process == nullptr) {
3322061da546Spatrick       result.AppendError(
3323061da546Spatrick           "You must have a process running to use this command.");
3324061da546Spatrick       return false;
3325061da546Spatrick     }
3326061da546Spatrick 
3327061da546Spatrick     ThreadList threads(process->GetThreadList());
3328061da546Spatrick     if (threads.GetSize() == 0) {
3329061da546Spatrick       result.AppendError("The process must be paused to use this command.");
3330061da546Spatrick       return false;
3331061da546Spatrick     }
3332061da546Spatrick 
3333061da546Spatrick     ThreadSP thread(threads.GetThreadAtIndex(0));
3334061da546Spatrick     if (!thread) {
3335061da546Spatrick       result.AppendError("The process must be paused to use this command.");
3336061da546Spatrick       return false;
3337061da546Spatrick     }
3338061da546Spatrick 
3339061da546Spatrick     SymbolContextList sc_list;
3340061da546Spatrick 
3341061da546Spatrick     if (m_options.m_type == eLookupTypeFunctionOrSymbol) {
3342061da546Spatrick       ConstString function_name(m_options.m_str.c_str());
3343*f6aab3d8Srobert       ModuleFunctionSearchOptions function_options;
3344*f6aab3d8Srobert       function_options.include_symbols = true;
3345*f6aab3d8Srobert       function_options.include_inlines = false;
3346061da546Spatrick       target->GetImages().FindFunctions(function_name, eFunctionNameTypeAuto,
3347*f6aab3d8Srobert                                         function_options, sc_list);
3348061da546Spatrick     } else if (m_options.m_type == eLookupTypeAddress && target) {
3349061da546Spatrick       Address addr;
3350061da546Spatrick       if (target->GetSectionLoadList().ResolveLoadAddress(m_options.m_addr,
3351061da546Spatrick                                                           addr)) {
3352061da546Spatrick         SymbolContext sc;
3353061da546Spatrick         ModuleSP module_sp(addr.GetModule());
3354061da546Spatrick         module_sp->ResolveSymbolContextForAddress(addr,
3355061da546Spatrick                                                   eSymbolContextEverything, sc);
3356061da546Spatrick         if (sc.function || sc.symbol) {
3357061da546Spatrick           sc_list.Append(sc);
3358061da546Spatrick         }
3359061da546Spatrick       }
3360061da546Spatrick     } else {
3361061da546Spatrick       result.AppendError(
3362061da546Spatrick           "address-expression or function name option must be specified.");
3363061da546Spatrick       return false;
3364061da546Spatrick     }
3365061da546Spatrick 
3366061da546Spatrick     size_t num_matches = sc_list.GetSize();
3367061da546Spatrick     if (num_matches == 0) {
3368061da546Spatrick       result.AppendErrorWithFormat("no unwind data found that matches '%s'.",
3369061da546Spatrick                                    m_options.m_str.c_str());
3370061da546Spatrick       return false;
3371061da546Spatrick     }
3372061da546Spatrick 
3373061da546Spatrick     for (uint32_t idx = 0; idx < num_matches; idx++) {
3374061da546Spatrick       SymbolContext sc;
3375061da546Spatrick       sc_list.GetContextAtIndex(idx, sc);
3376061da546Spatrick       if (sc.symbol == nullptr && sc.function == nullptr)
3377061da546Spatrick         continue;
3378061da546Spatrick       if (!sc.module_sp || sc.module_sp->GetObjectFile() == nullptr)
3379061da546Spatrick         continue;
3380061da546Spatrick       AddressRange range;
3381061da546Spatrick       if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0,
3382061da546Spatrick                               false, range))
3383061da546Spatrick         continue;
3384061da546Spatrick       if (!range.GetBaseAddress().IsValid())
3385061da546Spatrick         continue;
3386061da546Spatrick       ConstString funcname(sc.GetFunctionName());
3387061da546Spatrick       if (funcname.IsEmpty())
3388061da546Spatrick         continue;
3389061da546Spatrick       addr_t start_addr = range.GetBaseAddress().GetLoadAddress(target);
3390061da546Spatrick       if (abi)
3391061da546Spatrick         start_addr = abi->FixCodeAddress(start_addr);
3392061da546Spatrick 
3393061da546Spatrick       FuncUnwindersSP func_unwinders_sp(
3394061da546Spatrick           sc.module_sp->GetUnwindTable()
3395061da546Spatrick               .GetUncachedFuncUnwindersContainingAddress(start_addr, sc));
3396061da546Spatrick       if (!func_unwinders_sp)
3397061da546Spatrick         continue;
3398061da546Spatrick 
3399061da546Spatrick       result.GetOutputStream().Printf(
3400be691f3bSpatrick           "UNWIND PLANS for %s`%s (start addr 0x%" PRIx64 ")\n",
3401061da546Spatrick           sc.module_sp->GetPlatformFileSpec().GetFilename().AsCString(),
3402061da546Spatrick           funcname.AsCString(), start_addr);
3403061da546Spatrick 
3404be691f3bSpatrick       Args args;
3405be691f3bSpatrick       target->GetUserSpecifiedTrapHandlerNames(args);
3406be691f3bSpatrick       size_t count = args.GetArgumentCount();
3407be691f3bSpatrick       for (size_t i = 0; i < count; i++) {
3408be691f3bSpatrick         const char *trap_func_name = args.GetArgumentAtIndex(i);
3409be691f3bSpatrick         if (strcmp(funcname.GetCString(), trap_func_name) == 0)
3410be691f3bSpatrick           result.GetOutputStream().Printf(
3411be691f3bSpatrick               "This function is "
3412be691f3bSpatrick               "treated as a trap handler function via user setting.\n");
3413be691f3bSpatrick       }
3414be691f3bSpatrick       PlatformSP platform_sp(target->GetPlatform());
3415be691f3bSpatrick       if (platform_sp) {
3416be691f3bSpatrick         const std::vector<ConstString> trap_handler_names(
3417be691f3bSpatrick             platform_sp->GetTrapHandlerSymbolNames());
3418be691f3bSpatrick         for (ConstString trap_name : trap_handler_names) {
3419be691f3bSpatrick           if (trap_name == funcname) {
3420be691f3bSpatrick             result.GetOutputStream().Printf(
3421be691f3bSpatrick                 "This function's "
3422be691f3bSpatrick                 "name is listed by the platform as a trap handler.\n");
3423be691f3bSpatrick           }
3424be691f3bSpatrick         }
3425be691f3bSpatrick       }
3426be691f3bSpatrick 
3427be691f3bSpatrick       result.GetOutputStream().Printf("\n");
3428be691f3bSpatrick 
3429061da546Spatrick       UnwindPlanSP non_callsite_unwind_plan =
3430061da546Spatrick           func_unwinders_sp->GetUnwindPlanAtNonCallSite(*target, *thread);
3431061da546Spatrick       if (non_callsite_unwind_plan) {
3432061da546Spatrick         result.GetOutputStream().Printf(
3433061da546Spatrick             "Asynchronous (not restricted to call-sites) UnwindPlan is '%s'\n",
3434061da546Spatrick             non_callsite_unwind_plan->GetSourceName().AsCString());
3435061da546Spatrick       }
3436061da546Spatrick       UnwindPlanSP callsite_unwind_plan =
3437061da546Spatrick           func_unwinders_sp->GetUnwindPlanAtCallSite(*target, *thread);
3438061da546Spatrick       if (callsite_unwind_plan) {
3439061da546Spatrick         result.GetOutputStream().Printf(
3440061da546Spatrick             "Synchronous (restricted to call-sites) UnwindPlan is '%s'\n",
3441061da546Spatrick             callsite_unwind_plan->GetSourceName().AsCString());
3442061da546Spatrick       }
3443061da546Spatrick       UnwindPlanSP fast_unwind_plan =
3444061da546Spatrick           func_unwinders_sp->GetUnwindPlanFastUnwind(*target, *thread);
3445061da546Spatrick       if (fast_unwind_plan) {
3446061da546Spatrick         result.GetOutputStream().Printf(
3447061da546Spatrick             "Fast UnwindPlan is '%s'\n",
3448061da546Spatrick             fast_unwind_plan->GetSourceName().AsCString());
3449061da546Spatrick       }
3450061da546Spatrick 
3451061da546Spatrick       result.GetOutputStream().Printf("\n");
3452061da546Spatrick 
3453061da546Spatrick       UnwindPlanSP assembly_sp =
3454061da546Spatrick           func_unwinders_sp->GetAssemblyUnwindPlan(*target, *thread);
3455061da546Spatrick       if (assembly_sp) {
3456061da546Spatrick         result.GetOutputStream().Printf(
3457061da546Spatrick             "Assembly language inspection UnwindPlan:\n");
3458061da546Spatrick         assembly_sp->Dump(result.GetOutputStream(), thread.get(),
3459061da546Spatrick                           LLDB_INVALID_ADDRESS);
3460061da546Spatrick         result.GetOutputStream().Printf("\n");
3461061da546Spatrick       }
3462061da546Spatrick 
3463061da546Spatrick       UnwindPlanSP of_unwind_sp =
3464061da546Spatrick           func_unwinders_sp->GetObjectFileUnwindPlan(*target);
3465061da546Spatrick       if (of_unwind_sp) {
3466061da546Spatrick         result.GetOutputStream().Printf("object file UnwindPlan:\n");
3467061da546Spatrick         of_unwind_sp->Dump(result.GetOutputStream(), thread.get(),
3468061da546Spatrick                            LLDB_INVALID_ADDRESS);
3469061da546Spatrick         result.GetOutputStream().Printf("\n");
3470061da546Spatrick       }
3471061da546Spatrick 
3472061da546Spatrick       UnwindPlanSP of_unwind_augmented_sp =
3473061da546Spatrick           func_unwinders_sp->GetObjectFileAugmentedUnwindPlan(*target, *thread);
3474061da546Spatrick       if (of_unwind_augmented_sp) {
3475061da546Spatrick         result.GetOutputStream().Printf("object file augmented UnwindPlan:\n");
3476061da546Spatrick         of_unwind_augmented_sp->Dump(result.GetOutputStream(), thread.get(),
3477061da546Spatrick                                      LLDB_INVALID_ADDRESS);
3478061da546Spatrick         result.GetOutputStream().Printf("\n");
3479061da546Spatrick       }
3480061da546Spatrick 
3481061da546Spatrick       UnwindPlanSP ehframe_sp =
3482061da546Spatrick           func_unwinders_sp->GetEHFrameUnwindPlan(*target);
3483061da546Spatrick       if (ehframe_sp) {
3484061da546Spatrick         result.GetOutputStream().Printf("eh_frame UnwindPlan:\n");
3485061da546Spatrick         ehframe_sp->Dump(result.GetOutputStream(), thread.get(),
3486061da546Spatrick                          LLDB_INVALID_ADDRESS);
3487061da546Spatrick         result.GetOutputStream().Printf("\n");
3488061da546Spatrick       }
3489061da546Spatrick 
3490061da546Spatrick       UnwindPlanSP ehframe_augmented_sp =
3491061da546Spatrick           func_unwinders_sp->GetEHFrameAugmentedUnwindPlan(*target, *thread);
3492061da546Spatrick       if (ehframe_augmented_sp) {
3493061da546Spatrick         result.GetOutputStream().Printf("eh_frame augmented UnwindPlan:\n");
3494061da546Spatrick         ehframe_augmented_sp->Dump(result.GetOutputStream(), thread.get(),
3495061da546Spatrick                                    LLDB_INVALID_ADDRESS);
3496061da546Spatrick         result.GetOutputStream().Printf("\n");
3497061da546Spatrick       }
3498061da546Spatrick 
3499061da546Spatrick       if (UnwindPlanSP plan_sp =
3500061da546Spatrick               func_unwinders_sp->GetDebugFrameUnwindPlan(*target)) {
3501061da546Spatrick         result.GetOutputStream().Printf("debug_frame UnwindPlan:\n");
3502061da546Spatrick         plan_sp->Dump(result.GetOutputStream(), thread.get(),
3503061da546Spatrick                       LLDB_INVALID_ADDRESS);
3504061da546Spatrick         result.GetOutputStream().Printf("\n");
3505061da546Spatrick       }
3506061da546Spatrick 
3507061da546Spatrick       if (UnwindPlanSP plan_sp =
3508061da546Spatrick               func_unwinders_sp->GetDebugFrameAugmentedUnwindPlan(*target,
3509061da546Spatrick                                                                   *thread)) {
3510061da546Spatrick         result.GetOutputStream().Printf("debug_frame augmented UnwindPlan:\n");
3511061da546Spatrick         plan_sp->Dump(result.GetOutputStream(), thread.get(),
3512061da546Spatrick                       LLDB_INVALID_ADDRESS);
3513061da546Spatrick         result.GetOutputStream().Printf("\n");
3514061da546Spatrick       }
3515061da546Spatrick 
3516061da546Spatrick       UnwindPlanSP arm_unwind_sp =
3517061da546Spatrick           func_unwinders_sp->GetArmUnwindUnwindPlan(*target);
3518061da546Spatrick       if (arm_unwind_sp) {
3519061da546Spatrick         result.GetOutputStream().Printf("ARM.exidx unwind UnwindPlan:\n");
3520061da546Spatrick         arm_unwind_sp->Dump(result.GetOutputStream(), thread.get(),
3521061da546Spatrick                             LLDB_INVALID_ADDRESS);
3522061da546Spatrick         result.GetOutputStream().Printf("\n");
3523061da546Spatrick       }
3524061da546Spatrick 
3525061da546Spatrick       if (UnwindPlanSP symfile_plan_sp =
3526061da546Spatrick               func_unwinders_sp->GetSymbolFileUnwindPlan(*thread)) {
3527061da546Spatrick         result.GetOutputStream().Printf("Symbol file UnwindPlan:\n");
3528061da546Spatrick         symfile_plan_sp->Dump(result.GetOutputStream(), thread.get(),
3529061da546Spatrick                               LLDB_INVALID_ADDRESS);
3530061da546Spatrick         result.GetOutputStream().Printf("\n");
3531061da546Spatrick       }
3532061da546Spatrick 
3533061da546Spatrick       UnwindPlanSP compact_unwind_sp =
3534061da546Spatrick           func_unwinders_sp->GetCompactUnwindUnwindPlan(*target);
3535061da546Spatrick       if (compact_unwind_sp) {
3536061da546Spatrick         result.GetOutputStream().Printf("Compact unwind UnwindPlan:\n");
3537061da546Spatrick         compact_unwind_sp->Dump(result.GetOutputStream(), thread.get(),
3538061da546Spatrick                                 LLDB_INVALID_ADDRESS);
3539061da546Spatrick         result.GetOutputStream().Printf("\n");
3540061da546Spatrick       }
3541061da546Spatrick 
3542061da546Spatrick       if (fast_unwind_plan) {
3543061da546Spatrick         result.GetOutputStream().Printf("Fast UnwindPlan:\n");
3544061da546Spatrick         fast_unwind_plan->Dump(result.GetOutputStream(), thread.get(),
3545061da546Spatrick                                LLDB_INVALID_ADDRESS);
3546061da546Spatrick         result.GetOutputStream().Printf("\n");
3547061da546Spatrick       }
3548061da546Spatrick 
3549061da546Spatrick       ABISP abi_sp = process->GetABI();
3550061da546Spatrick       if (abi_sp) {
3551061da546Spatrick         UnwindPlan arch_default(lldb::eRegisterKindGeneric);
3552061da546Spatrick         if (abi_sp->CreateDefaultUnwindPlan(arch_default)) {
3553061da546Spatrick           result.GetOutputStream().Printf("Arch default UnwindPlan:\n");
3554061da546Spatrick           arch_default.Dump(result.GetOutputStream(), thread.get(),
3555061da546Spatrick                             LLDB_INVALID_ADDRESS);
3556061da546Spatrick           result.GetOutputStream().Printf("\n");
3557061da546Spatrick         }
3558061da546Spatrick 
3559061da546Spatrick         UnwindPlan arch_entry(lldb::eRegisterKindGeneric);
3560061da546Spatrick         if (abi_sp->CreateFunctionEntryUnwindPlan(arch_entry)) {
3561061da546Spatrick           result.GetOutputStream().Printf(
3562061da546Spatrick               "Arch default at entry point UnwindPlan:\n");
3563061da546Spatrick           arch_entry.Dump(result.GetOutputStream(), thread.get(),
3564061da546Spatrick                           LLDB_INVALID_ADDRESS);
3565061da546Spatrick           result.GetOutputStream().Printf("\n");
3566061da546Spatrick         }
3567061da546Spatrick       }
3568061da546Spatrick 
3569061da546Spatrick       result.GetOutputStream().Printf("\n");
3570061da546Spatrick     }
3571061da546Spatrick     return result.Succeeded();
3572061da546Spatrick   }
3573061da546Spatrick 
3574061da546Spatrick   CommandOptions m_options;
3575061da546Spatrick };
3576061da546Spatrick 
3577061da546Spatrick // Lookup information in images
3578061da546Spatrick #define LLDB_OPTIONS_target_modules_lookup
3579061da546Spatrick #include "CommandOptions.inc"
3580061da546Spatrick 
3581061da546Spatrick class CommandObjectTargetModulesLookup : public CommandObjectParsed {
3582061da546Spatrick public:
3583061da546Spatrick   enum {
3584061da546Spatrick     eLookupTypeInvalid = -1,
3585061da546Spatrick     eLookupTypeAddress = 0,
3586061da546Spatrick     eLookupTypeSymbol,
3587061da546Spatrick     eLookupTypeFileLine, // Line is optional
3588061da546Spatrick     eLookupTypeFunction,
3589061da546Spatrick     eLookupTypeFunctionOrSymbol,
3590061da546Spatrick     eLookupTypeType,
3591061da546Spatrick     kNumLookupTypes
3592061da546Spatrick   };
3593061da546Spatrick 
3594061da546Spatrick   class CommandOptions : public Options {
3595061da546Spatrick   public:
CommandOptions()3596*f6aab3d8Srobert     CommandOptions() { OptionParsingStarting(nullptr); }
3597061da546Spatrick 
3598061da546Spatrick     ~CommandOptions() override = default;
3599061da546Spatrick 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)3600061da546Spatrick     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
3601061da546Spatrick                           ExecutionContext *execution_context) override {
3602061da546Spatrick       Status error;
3603061da546Spatrick 
3604061da546Spatrick       const int short_option = m_getopt_table[option_idx].val;
3605061da546Spatrick 
3606061da546Spatrick       switch (short_option) {
3607061da546Spatrick       case 'a': {
3608061da546Spatrick         m_type = eLookupTypeAddress;
3609061da546Spatrick         m_addr = OptionArgParser::ToAddress(execution_context, option_arg,
3610061da546Spatrick                                             LLDB_INVALID_ADDRESS, &error);
3611061da546Spatrick       } break;
3612061da546Spatrick 
3613061da546Spatrick       case 'o':
3614061da546Spatrick         if (option_arg.getAsInteger(0, m_offset))
3615061da546Spatrick           error.SetErrorStringWithFormat("invalid offset string '%s'",
3616061da546Spatrick                                          option_arg.str().c_str());
3617061da546Spatrick         break;
3618061da546Spatrick 
3619061da546Spatrick       case 's':
3620dda28197Spatrick         m_str = std::string(option_arg);
3621061da546Spatrick         m_type = eLookupTypeSymbol;
3622061da546Spatrick         break;
3623061da546Spatrick 
3624061da546Spatrick       case 'f':
3625061da546Spatrick         m_file.SetFile(option_arg, FileSpec::Style::native);
3626061da546Spatrick         m_type = eLookupTypeFileLine;
3627061da546Spatrick         break;
3628061da546Spatrick 
3629061da546Spatrick       case 'i':
3630061da546Spatrick         m_include_inlines = false;
3631061da546Spatrick         break;
3632061da546Spatrick 
3633061da546Spatrick       case 'l':
3634061da546Spatrick         if (option_arg.getAsInteger(0, m_line_number))
3635061da546Spatrick           error.SetErrorStringWithFormat("invalid line number string '%s'",
3636061da546Spatrick                                          option_arg.str().c_str());
3637061da546Spatrick         else if (m_line_number == 0)
3638061da546Spatrick           error.SetErrorString("zero is an invalid line number");
3639061da546Spatrick         m_type = eLookupTypeFileLine;
3640061da546Spatrick         break;
3641061da546Spatrick 
3642061da546Spatrick       case 'F':
3643dda28197Spatrick         m_str = std::string(option_arg);
3644061da546Spatrick         m_type = eLookupTypeFunction;
3645061da546Spatrick         break;
3646061da546Spatrick 
3647061da546Spatrick       case 'n':
3648dda28197Spatrick         m_str = std::string(option_arg);
3649061da546Spatrick         m_type = eLookupTypeFunctionOrSymbol;
3650061da546Spatrick         break;
3651061da546Spatrick 
3652061da546Spatrick       case 't':
3653dda28197Spatrick         m_str = std::string(option_arg);
3654061da546Spatrick         m_type = eLookupTypeType;
3655061da546Spatrick         break;
3656061da546Spatrick 
3657061da546Spatrick       case 'v':
3658061da546Spatrick         m_verbose = true;
3659061da546Spatrick         break;
3660061da546Spatrick 
3661061da546Spatrick       case 'A':
3662061da546Spatrick         m_print_all = true;
3663061da546Spatrick         break;
3664061da546Spatrick 
3665061da546Spatrick       case 'r':
3666061da546Spatrick         m_use_regex = true;
3667061da546Spatrick         break;
3668*f6aab3d8Srobert 
3669*f6aab3d8Srobert       case '\x01':
3670*f6aab3d8Srobert         m_all_ranges = true;
3671*f6aab3d8Srobert         break;
3672061da546Spatrick       default:
3673061da546Spatrick         llvm_unreachable("Unimplemented option");
3674061da546Spatrick       }
3675061da546Spatrick 
3676061da546Spatrick       return error;
3677061da546Spatrick     }
3678061da546Spatrick 
OptionParsingStarting(ExecutionContext * execution_context)3679061da546Spatrick     void OptionParsingStarting(ExecutionContext *execution_context) override {
3680061da546Spatrick       m_type = eLookupTypeInvalid;
3681061da546Spatrick       m_str.clear();
3682061da546Spatrick       m_file.Clear();
3683061da546Spatrick       m_addr = LLDB_INVALID_ADDRESS;
3684061da546Spatrick       m_offset = 0;
3685061da546Spatrick       m_line_number = 0;
3686061da546Spatrick       m_use_regex = false;
3687061da546Spatrick       m_include_inlines = true;
3688*f6aab3d8Srobert       m_all_ranges = false;
3689061da546Spatrick       m_verbose = false;
3690061da546Spatrick       m_print_all = false;
3691061da546Spatrick     }
3692061da546Spatrick 
OptionParsingFinished(ExecutionContext * execution_context)3693*f6aab3d8Srobert     Status OptionParsingFinished(ExecutionContext *execution_context) override {
3694*f6aab3d8Srobert       Status status;
3695*f6aab3d8Srobert       if (m_all_ranges && !m_verbose) {
3696*f6aab3d8Srobert         status.SetErrorString("--show-variable-ranges must be used in "
3697*f6aab3d8Srobert                               "conjunction with --verbose.");
3698*f6aab3d8Srobert       }
3699*f6aab3d8Srobert       return status;
3700*f6aab3d8Srobert     }
3701*f6aab3d8Srobert 
GetDefinitions()3702061da546Spatrick     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
3703*f6aab3d8Srobert       return llvm::ArrayRef(g_target_modules_lookup_options);
3704061da546Spatrick     }
3705061da546Spatrick 
3706061da546Spatrick     int m_type;        // Should be a eLookupTypeXXX enum after parsing options
3707061da546Spatrick     std::string m_str; // Holds name lookup
3708061da546Spatrick     FileSpec m_file;   // Files for file lookups
3709061da546Spatrick     lldb::addr_t m_addr; // Holds the address to lookup
3710061da546Spatrick     lldb::addr_t
3711061da546Spatrick         m_offset; // Subtract this offset from m_addr before doing lookups.
3712061da546Spatrick     uint32_t m_line_number; // Line number for file+line lookups
3713061da546Spatrick     bool m_use_regex;       // Name lookups in m_str are regular expressions.
3714061da546Spatrick     bool m_include_inlines; // Check for inline entries when looking up by
3715061da546Spatrick                             // file/line.
3716*f6aab3d8Srobert     bool m_all_ranges;      // Print all ranges or single range.
3717061da546Spatrick     bool m_verbose;         // Enable verbose lookup info
3718061da546Spatrick     bool m_print_all; // Print all matches, even in cases where there's a best
3719061da546Spatrick                       // match.
3720061da546Spatrick   };
3721061da546Spatrick 
CommandObjectTargetModulesLookup(CommandInterpreter & interpreter)3722061da546Spatrick   CommandObjectTargetModulesLookup(CommandInterpreter &interpreter)
3723061da546Spatrick       : CommandObjectParsed(interpreter, "target modules lookup",
3724061da546Spatrick                             "Look up information within executable and "
3725061da546Spatrick                             "dependent shared library images.",
3726*f6aab3d8Srobert                             nullptr, eCommandRequiresTarget) {
3727061da546Spatrick     CommandArgumentEntry arg;
3728061da546Spatrick     CommandArgumentData file_arg;
3729061da546Spatrick 
3730061da546Spatrick     // Define the first (and only) variant of this arg.
3731061da546Spatrick     file_arg.arg_type = eArgTypeFilename;
3732061da546Spatrick     file_arg.arg_repetition = eArgRepeatStar;
3733061da546Spatrick 
3734061da546Spatrick     // There is only one variant this argument could be; put it into the
3735061da546Spatrick     // argument entry.
3736061da546Spatrick     arg.push_back(file_arg);
3737061da546Spatrick 
3738061da546Spatrick     // Push the data for the first argument into the m_arguments vector.
3739061da546Spatrick     m_arguments.push_back(arg);
3740061da546Spatrick   }
3741061da546Spatrick 
3742061da546Spatrick   ~CommandObjectTargetModulesLookup() override = default;
3743061da546Spatrick 
GetOptions()3744061da546Spatrick   Options *GetOptions() override { return &m_options; }
3745061da546Spatrick 
LookupHere(CommandInterpreter & interpreter,CommandReturnObject & result,bool & syntax_error)3746061da546Spatrick   bool LookupHere(CommandInterpreter &interpreter, CommandReturnObject &result,
3747061da546Spatrick                   bool &syntax_error) {
3748061da546Spatrick     switch (m_options.m_type) {
3749061da546Spatrick     case eLookupTypeAddress:
3750061da546Spatrick     case eLookupTypeFileLine:
3751061da546Spatrick     case eLookupTypeFunction:
3752061da546Spatrick     case eLookupTypeFunctionOrSymbol:
3753061da546Spatrick     case eLookupTypeSymbol:
3754061da546Spatrick     default:
3755061da546Spatrick       return false;
3756061da546Spatrick     case eLookupTypeType:
3757061da546Spatrick       break;
3758061da546Spatrick     }
3759061da546Spatrick 
3760061da546Spatrick     StackFrameSP frame = m_exe_ctx.GetFrameSP();
3761061da546Spatrick 
3762061da546Spatrick     if (!frame)
3763061da546Spatrick       return false;
3764061da546Spatrick 
3765061da546Spatrick     const SymbolContext &sym_ctx(frame->GetSymbolContext(eSymbolContextModule));
3766061da546Spatrick 
3767061da546Spatrick     if (!sym_ctx.module_sp)
3768061da546Spatrick       return false;
3769061da546Spatrick 
3770061da546Spatrick     switch (m_options.m_type) {
3771061da546Spatrick     default:
3772061da546Spatrick       return false;
3773061da546Spatrick     case eLookupTypeType:
3774061da546Spatrick       if (!m_options.m_str.empty()) {
3775be691f3bSpatrick         if (LookupTypeHere(&GetSelectedTarget(), m_interpreter,
3776be691f3bSpatrick                            result.GetOutputStream(), *sym_ctx.module_sp,
3777be691f3bSpatrick                            m_options.m_str.c_str(), m_options.m_use_regex)) {
3778061da546Spatrick           result.SetStatus(eReturnStatusSuccessFinishResult);
3779061da546Spatrick           return true;
3780061da546Spatrick         }
3781061da546Spatrick       }
3782061da546Spatrick       break;
3783061da546Spatrick     }
3784061da546Spatrick 
3785061da546Spatrick     return false;
3786061da546Spatrick   }
3787061da546Spatrick 
LookupInModule(CommandInterpreter & interpreter,Module * module,CommandReturnObject & result,bool & syntax_error)3788061da546Spatrick   bool LookupInModule(CommandInterpreter &interpreter, Module *module,
3789061da546Spatrick                       CommandReturnObject &result, bool &syntax_error) {
3790061da546Spatrick     switch (m_options.m_type) {
3791061da546Spatrick     case eLookupTypeAddress:
3792061da546Spatrick       if (m_options.m_addr != LLDB_INVALID_ADDRESS) {
3793061da546Spatrick         if (LookupAddressInModule(
3794061da546Spatrick                 m_interpreter, result.GetOutputStream(), module,
3795061da546Spatrick                 eSymbolContextEverything |
3796061da546Spatrick                     (m_options.m_verbose
3797061da546Spatrick                          ? static_cast<int>(eSymbolContextVariable)
3798061da546Spatrick                          : 0),
3799*f6aab3d8Srobert                 m_options.m_addr, m_options.m_offset, m_options.m_verbose,
3800*f6aab3d8Srobert                 m_options.m_all_ranges)) {
3801061da546Spatrick           result.SetStatus(eReturnStatusSuccessFinishResult);
3802061da546Spatrick           return true;
3803061da546Spatrick         }
3804061da546Spatrick       }
3805061da546Spatrick       break;
3806061da546Spatrick 
3807061da546Spatrick     case eLookupTypeSymbol:
3808061da546Spatrick       if (!m_options.m_str.empty()) {
3809061da546Spatrick         if (LookupSymbolInModule(m_interpreter, result.GetOutputStream(),
3810061da546Spatrick                                  module, m_options.m_str.c_str(),
3811*f6aab3d8Srobert                                  m_options.m_use_regex, m_options.m_verbose,
3812*f6aab3d8Srobert                                  m_options.m_all_ranges)) {
3813061da546Spatrick           result.SetStatus(eReturnStatusSuccessFinishResult);
3814061da546Spatrick           return true;
3815061da546Spatrick         }
3816061da546Spatrick       }
3817061da546Spatrick       break;
3818061da546Spatrick 
3819061da546Spatrick     case eLookupTypeFileLine:
3820061da546Spatrick       if (m_options.m_file) {
3821061da546Spatrick         if (LookupFileAndLineInModule(
3822061da546Spatrick                 m_interpreter, result.GetOutputStream(), module,
3823061da546Spatrick                 m_options.m_file, m_options.m_line_number,
3824*f6aab3d8Srobert                 m_options.m_include_inlines, m_options.m_verbose,
3825*f6aab3d8Srobert                 m_options.m_all_ranges)) {
3826061da546Spatrick           result.SetStatus(eReturnStatusSuccessFinishResult);
3827061da546Spatrick           return true;
3828061da546Spatrick         }
3829061da546Spatrick       }
3830061da546Spatrick       break;
3831061da546Spatrick 
3832061da546Spatrick     case eLookupTypeFunctionOrSymbol:
3833061da546Spatrick     case eLookupTypeFunction:
3834061da546Spatrick       if (!m_options.m_str.empty()) {
3835*f6aab3d8Srobert         ModuleFunctionSearchOptions function_options;
3836*f6aab3d8Srobert         function_options.include_symbols =
3837*f6aab3d8Srobert             m_options.m_type == eLookupTypeFunctionOrSymbol;
3838*f6aab3d8Srobert         function_options.include_inlines = m_options.m_include_inlines;
3839*f6aab3d8Srobert 
3840*f6aab3d8Srobert         if (LookupFunctionInModule(m_interpreter, result.GetOutputStream(),
3841*f6aab3d8Srobert                                    module, m_options.m_str.c_str(),
3842*f6aab3d8Srobert                                    m_options.m_use_regex, function_options,
3843*f6aab3d8Srobert                                    m_options.m_verbose,
3844*f6aab3d8Srobert                                    m_options.m_all_ranges)) {
3845061da546Spatrick           result.SetStatus(eReturnStatusSuccessFinishResult);
3846061da546Spatrick           return true;
3847061da546Spatrick         }
3848061da546Spatrick       }
3849061da546Spatrick       break;
3850061da546Spatrick 
3851061da546Spatrick     case eLookupTypeType:
3852061da546Spatrick       if (!m_options.m_str.empty()) {
3853be691f3bSpatrick         if (LookupTypeInModule(
3854be691f3bSpatrick                 &GetSelectedTarget(), m_interpreter, result.GetOutputStream(),
3855be691f3bSpatrick                 module, m_options.m_str.c_str(), m_options.m_use_regex)) {
3856061da546Spatrick           result.SetStatus(eReturnStatusSuccessFinishResult);
3857061da546Spatrick           return true;
3858061da546Spatrick         }
3859061da546Spatrick       }
3860061da546Spatrick       break;
3861061da546Spatrick 
3862061da546Spatrick     default:
3863061da546Spatrick       m_options.GenerateOptionUsage(
3864*f6aab3d8Srobert           result.GetErrorStream(), *this,
3865061da546Spatrick           GetCommandInterpreter().GetDebugger().GetTerminalWidth());
3866061da546Spatrick       syntax_error = true;
3867061da546Spatrick       break;
3868061da546Spatrick     }
3869061da546Spatrick 
3870061da546Spatrick     result.SetStatus(eReturnStatusFailed);
3871061da546Spatrick     return false;
3872061da546Spatrick   }
3873061da546Spatrick 
3874061da546Spatrick protected:
DoExecute(Args & command,CommandReturnObject & result)3875061da546Spatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
3876061da546Spatrick     Target *target = &GetSelectedTarget();
3877061da546Spatrick     bool syntax_error = false;
3878061da546Spatrick     uint32_t i;
3879061da546Spatrick     uint32_t num_successful_lookups = 0;
3880061da546Spatrick     uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
3881061da546Spatrick     result.GetOutputStream().SetAddressByteSize(addr_byte_size);
3882061da546Spatrick     result.GetErrorStream().SetAddressByteSize(addr_byte_size);
3883061da546Spatrick     // Dump all sections for all modules images
3884061da546Spatrick 
3885061da546Spatrick     if (command.GetArgumentCount() == 0) {
3886061da546Spatrick       ModuleSP current_module;
3887061da546Spatrick 
3888061da546Spatrick       // Where it is possible to look in the current symbol context first,
3889061da546Spatrick       // try that.  If this search was successful and --all was not passed,
3890061da546Spatrick       // don't print anything else.
3891061da546Spatrick       if (LookupHere(m_interpreter, result, syntax_error)) {
3892061da546Spatrick         result.GetOutputStream().EOL();
3893061da546Spatrick         num_successful_lookups++;
3894061da546Spatrick         if (!m_options.m_print_all) {
3895061da546Spatrick           result.SetStatus(eReturnStatusSuccessFinishResult);
3896061da546Spatrick           return result.Succeeded();
3897061da546Spatrick         }
3898061da546Spatrick       }
3899061da546Spatrick 
3900061da546Spatrick       // Dump all sections for all other modules
3901061da546Spatrick 
3902061da546Spatrick       const ModuleList &target_modules = target->GetImages();
3903061da546Spatrick       std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
3904be691f3bSpatrick       if (target_modules.GetSize() == 0) {
3905be691f3bSpatrick         result.AppendError("the target has no associated executable images");
3906be691f3bSpatrick         return false;
3907be691f3bSpatrick       }
3908061da546Spatrick 
3909be691f3bSpatrick       for (ModuleSP module_sp : target_modules.ModulesNoLocking()) {
3910be691f3bSpatrick         if (module_sp != current_module &&
3911be691f3bSpatrick             LookupInModule(m_interpreter, module_sp.get(), result,
3912be691f3bSpatrick                            syntax_error)) {
3913061da546Spatrick           result.GetOutputStream().EOL();
3914061da546Spatrick           num_successful_lookups++;
3915061da546Spatrick         }
3916061da546Spatrick       }
3917061da546Spatrick     } else {
3918061da546Spatrick       // Dump specified images (by basename or fullpath)
3919061da546Spatrick       const char *arg_cstr;
3920061da546Spatrick       for (i = 0; (arg_cstr = command.GetArgumentAtIndex(i)) != nullptr &&
3921061da546Spatrick                   !syntax_error;
3922061da546Spatrick            ++i) {
3923061da546Spatrick         ModuleList module_list;
3924061da546Spatrick         const size_t num_matches =
3925061da546Spatrick             FindModulesByName(target, arg_cstr, module_list, false);
3926061da546Spatrick         if (num_matches > 0) {
3927061da546Spatrick           for (size_t j = 0; j < num_matches; ++j) {
3928061da546Spatrick             Module *module = module_list.GetModulePointerAtIndex(j);
3929061da546Spatrick             if (module) {
3930061da546Spatrick               if (LookupInModule(m_interpreter, module, result, syntax_error)) {
3931061da546Spatrick                 result.GetOutputStream().EOL();
3932061da546Spatrick                 num_successful_lookups++;
3933061da546Spatrick               }
3934061da546Spatrick             }
3935061da546Spatrick           }
3936061da546Spatrick         } else
3937061da546Spatrick           result.AppendWarningWithFormat(
3938061da546Spatrick               "Unable to find an image that matches '%s'.\n", arg_cstr);
3939061da546Spatrick       }
3940061da546Spatrick     }
3941061da546Spatrick 
3942061da546Spatrick     if (num_successful_lookups > 0)
3943061da546Spatrick       result.SetStatus(eReturnStatusSuccessFinishResult);
3944061da546Spatrick     else
3945061da546Spatrick       result.SetStatus(eReturnStatusFailed);
3946061da546Spatrick     return result.Succeeded();
3947061da546Spatrick   }
3948061da546Spatrick 
3949061da546Spatrick   CommandOptions m_options;
3950061da546Spatrick };
3951061da546Spatrick 
3952061da546Spatrick #pragma mark CommandObjectMultiwordImageSearchPaths
3953061da546Spatrick 
3954061da546Spatrick // CommandObjectMultiwordImageSearchPaths
3955061da546Spatrick 
3956061da546Spatrick class CommandObjectTargetModulesImageSearchPaths
3957061da546Spatrick     : public CommandObjectMultiword {
3958061da546Spatrick public:
CommandObjectTargetModulesImageSearchPaths(CommandInterpreter & interpreter)3959061da546Spatrick   CommandObjectTargetModulesImageSearchPaths(CommandInterpreter &interpreter)
3960061da546Spatrick       : CommandObjectMultiword(
3961061da546Spatrick             interpreter, "target modules search-paths",
3962061da546Spatrick             "Commands for managing module search paths for a target.",
3963061da546Spatrick             "target modules search-paths <subcommand> [<subcommand-options>]") {
3964061da546Spatrick     LoadSubCommand(
3965061da546Spatrick         "add", CommandObjectSP(
3966061da546Spatrick                    new CommandObjectTargetModulesSearchPathsAdd(interpreter)));
3967061da546Spatrick     LoadSubCommand(
3968061da546Spatrick         "clear", CommandObjectSP(new CommandObjectTargetModulesSearchPathsClear(
3969061da546Spatrick                      interpreter)));
3970061da546Spatrick     LoadSubCommand(
3971061da546Spatrick         "insert",
3972061da546Spatrick         CommandObjectSP(
3973061da546Spatrick             new CommandObjectTargetModulesSearchPathsInsert(interpreter)));
3974061da546Spatrick     LoadSubCommand(
3975061da546Spatrick         "list", CommandObjectSP(new CommandObjectTargetModulesSearchPathsList(
3976061da546Spatrick                     interpreter)));
3977061da546Spatrick     LoadSubCommand(
3978061da546Spatrick         "query", CommandObjectSP(new CommandObjectTargetModulesSearchPathsQuery(
3979061da546Spatrick                      interpreter)));
3980061da546Spatrick   }
3981061da546Spatrick 
3982061da546Spatrick   ~CommandObjectTargetModulesImageSearchPaths() override = default;
3983061da546Spatrick };
3984061da546Spatrick 
3985061da546Spatrick #pragma mark CommandObjectTargetModules
3986061da546Spatrick 
3987061da546Spatrick // CommandObjectTargetModules
3988061da546Spatrick 
3989061da546Spatrick class CommandObjectTargetModules : public CommandObjectMultiword {
3990061da546Spatrick public:
3991061da546Spatrick   // Constructors and Destructors
CommandObjectTargetModules(CommandInterpreter & interpreter)3992061da546Spatrick   CommandObjectTargetModules(CommandInterpreter &interpreter)
3993061da546Spatrick       : CommandObjectMultiword(interpreter, "target modules",
3994061da546Spatrick                                "Commands for accessing information for one or "
3995061da546Spatrick                                "more target modules.",
3996061da546Spatrick                                "target modules <sub-command> ...") {
3997061da546Spatrick     LoadSubCommand(
3998061da546Spatrick         "add", CommandObjectSP(new CommandObjectTargetModulesAdd(interpreter)));
3999061da546Spatrick     LoadSubCommand("load", CommandObjectSP(new CommandObjectTargetModulesLoad(
4000061da546Spatrick                                interpreter)));
4001061da546Spatrick     LoadSubCommand("dump", CommandObjectSP(new CommandObjectTargetModulesDump(
4002061da546Spatrick                                interpreter)));
4003061da546Spatrick     LoadSubCommand("list", CommandObjectSP(new CommandObjectTargetModulesList(
4004061da546Spatrick                                interpreter)));
4005061da546Spatrick     LoadSubCommand(
4006061da546Spatrick         "lookup",
4007061da546Spatrick         CommandObjectSP(new CommandObjectTargetModulesLookup(interpreter)));
4008061da546Spatrick     LoadSubCommand(
4009061da546Spatrick         "search-paths",
4010061da546Spatrick         CommandObjectSP(
4011061da546Spatrick             new CommandObjectTargetModulesImageSearchPaths(interpreter)));
4012061da546Spatrick     LoadSubCommand(
4013061da546Spatrick         "show-unwind",
4014061da546Spatrick         CommandObjectSP(new CommandObjectTargetModulesShowUnwind(interpreter)));
4015061da546Spatrick   }
4016061da546Spatrick 
4017061da546Spatrick   ~CommandObjectTargetModules() override = default;
4018061da546Spatrick 
4019061da546Spatrick private:
4020061da546Spatrick   // For CommandObjectTargetModules only
4021dda28197Spatrick   CommandObjectTargetModules(const CommandObjectTargetModules &) = delete;
4022dda28197Spatrick   const CommandObjectTargetModules &
4023dda28197Spatrick   operator=(const CommandObjectTargetModules &) = delete;
4024061da546Spatrick };
4025061da546Spatrick 
4026061da546Spatrick class CommandObjectTargetSymbolsAdd : public CommandObjectParsed {
4027061da546Spatrick public:
CommandObjectTargetSymbolsAdd(CommandInterpreter & interpreter)4028061da546Spatrick   CommandObjectTargetSymbolsAdd(CommandInterpreter &interpreter)
4029061da546Spatrick       : CommandObjectParsed(
4030061da546Spatrick             interpreter, "target symbols add",
4031061da546Spatrick             "Add a debug symbol file to one of the target's current modules by "
4032dda28197Spatrick             "specifying a path to a debug symbols file or by using the options "
4033dda28197Spatrick             "to specify a module.",
4034061da546Spatrick             "target symbols add <cmd-options> [<symfile>]",
4035061da546Spatrick             eCommandRequiresTarget),
4036061da546Spatrick         m_file_option(
4037061da546Spatrick             LLDB_OPT_SET_1, false, "shlib", 's',
4038061da546Spatrick             CommandCompletions::eModuleCompletion, eArgTypeShlibName,
4039dda28197Spatrick             "Locate the debug symbols for the shared library specified by "
4040dda28197Spatrick             "name."),
4041061da546Spatrick         m_current_frame_option(
4042061da546Spatrick             LLDB_OPT_SET_2, false, "frame", 'F',
4043*f6aab3d8Srobert             "Locate the debug symbols for the currently selected frame.", false,
4044*f6aab3d8Srobert             true),
4045*f6aab3d8Srobert         m_current_stack_option(LLDB_OPT_SET_2, false, "stack", 'S',
4046*f6aab3d8Srobert                                "Locate the debug symbols for every frame in "
4047*f6aab3d8Srobert                                "the current call stack.",
4048dda28197Spatrick                                false, true)
4049061da546Spatrick 
4050061da546Spatrick   {
4051061da546Spatrick     m_option_group.Append(&m_uuid_option_group, LLDB_OPT_SET_ALL,
4052061da546Spatrick                           LLDB_OPT_SET_1);
4053061da546Spatrick     m_option_group.Append(&m_file_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
4054061da546Spatrick     m_option_group.Append(&m_current_frame_option, LLDB_OPT_SET_2,
4055061da546Spatrick                           LLDB_OPT_SET_2);
4056*f6aab3d8Srobert     m_option_group.Append(&m_current_stack_option, LLDB_OPT_SET_2,
4057*f6aab3d8Srobert                           LLDB_OPT_SET_2);
4058061da546Spatrick     m_option_group.Finalize();
4059*f6aab3d8Srobert     CommandArgumentData module_arg{eArgTypeShlibName, eArgRepeatPlain};
4060*f6aab3d8Srobert     m_arguments.push_back({module_arg});
4061061da546Spatrick   }
4062061da546Spatrick 
4063061da546Spatrick   ~CommandObjectTargetSymbolsAdd() override = default;
4064061da546Spatrick 
4065061da546Spatrick   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)4066061da546Spatrick   HandleArgumentCompletion(CompletionRequest &request,
4067061da546Spatrick                            OptionElementVector &opt_element_vector) override {
4068061da546Spatrick     CommandCompletions::InvokeCommonCompletionCallbacks(
4069061da546Spatrick         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
4070061da546Spatrick         request, nullptr);
4071061da546Spatrick   }
4072061da546Spatrick 
GetOptions()4073061da546Spatrick   Options *GetOptions() override { return &m_option_group; }
4074061da546Spatrick 
4075061da546Spatrick protected:
AddModuleSymbols(Target * target,ModuleSpec & module_spec,bool & flush,CommandReturnObject & result)4076061da546Spatrick   bool AddModuleSymbols(Target *target, ModuleSpec &module_spec, bool &flush,
4077061da546Spatrick                         CommandReturnObject &result) {
4078061da546Spatrick     const FileSpec &symbol_fspec = module_spec.GetSymbolFileSpec();
4079061da546Spatrick     if (!symbol_fspec) {
4080061da546Spatrick       result.AppendError(
4081061da546Spatrick           "one or more executable image paths must be specified");
4082061da546Spatrick       return false;
4083061da546Spatrick     }
4084061da546Spatrick 
4085061da546Spatrick     char symfile_path[PATH_MAX];
4086061da546Spatrick     symbol_fspec.GetPath(symfile_path, sizeof(symfile_path));
4087061da546Spatrick 
4088061da546Spatrick     if (!module_spec.GetUUID().IsValid()) {
4089061da546Spatrick       if (!module_spec.GetFileSpec() && !module_spec.GetPlatformFileSpec())
4090*f6aab3d8Srobert         module_spec.GetFileSpec().SetFilename(symbol_fspec.GetFilename());
4091061da546Spatrick     }
4092061da546Spatrick 
4093dda28197Spatrick     // Now module_spec represents a symbol file for a module that might exist
4094dda28197Spatrick     // in the current target.  Let's find possible matches.
4095dda28197Spatrick     ModuleList matching_modules;
4096061da546Spatrick 
4097061da546Spatrick     // First extract all module specs from the symbol file
4098061da546Spatrick     lldb_private::ModuleSpecList symfile_module_specs;
4099061da546Spatrick     if (ObjectFile::GetModuleSpecifications(module_spec.GetSymbolFileSpec(),
4100061da546Spatrick                                             0, 0, symfile_module_specs)) {
4101061da546Spatrick       // Now extract the module spec that matches the target architecture
4102061da546Spatrick       ModuleSpec target_arch_module_spec;
4103061da546Spatrick       ModuleSpec symfile_module_spec;
4104061da546Spatrick       target_arch_module_spec.GetArchitecture() = target->GetArchitecture();
4105061da546Spatrick       if (symfile_module_specs.FindMatchingModuleSpec(target_arch_module_spec,
4106061da546Spatrick                                                       symfile_module_spec)) {
4107061da546Spatrick         if (symfile_module_spec.GetUUID().IsValid()) {
4108061da546Spatrick           // It has a UUID, look for this UUID in the target modules
4109061da546Spatrick           ModuleSpec symfile_uuid_module_spec;
4110061da546Spatrick           symfile_uuid_module_spec.GetUUID() = symfile_module_spec.GetUUID();
4111061da546Spatrick           target->GetImages().FindModules(symfile_uuid_module_spec,
4112dda28197Spatrick                                           matching_modules);
4113061da546Spatrick         }
4114061da546Spatrick       }
4115061da546Spatrick 
4116dda28197Spatrick       if (matching_modules.IsEmpty()) {
4117dda28197Spatrick         // No matches yet.  Iterate through the module specs to find a UUID
4118dda28197Spatrick         // value that we can match up to an image in our target.
4119dda28197Spatrick         const size_t num_symfile_module_specs = symfile_module_specs.GetSize();
4120dda28197Spatrick         for (size_t i = 0;
4121dda28197Spatrick              i < num_symfile_module_specs && matching_modules.IsEmpty(); ++i) {
4122061da546Spatrick           if (symfile_module_specs.GetModuleSpecAtIndex(
4123061da546Spatrick                   i, symfile_module_spec)) {
4124061da546Spatrick             if (symfile_module_spec.GetUUID().IsValid()) {
4125dda28197Spatrick               // It has a UUID.  Look for this UUID in the target modules.
4126061da546Spatrick               ModuleSpec symfile_uuid_module_spec;
4127061da546Spatrick               symfile_uuid_module_spec.GetUUID() =
4128061da546Spatrick                   symfile_module_spec.GetUUID();
4129061da546Spatrick               target->GetImages().FindModules(symfile_uuid_module_spec,
4130dda28197Spatrick                                               matching_modules);
4131061da546Spatrick             }
4132061da546Spatrick           }
4133061da546Spatrick         }
4134061da546Spatrick       }
4135061da546Spatrick     }
4136061da546Spatrick 
4137061da546Spatrick     // Just try to match up the file by basename if we have no matches at
4138dda28197Spatrick     // this point.  For example, module foo might have symbols in foo.debug.
4139dda28197Spatrick     if (matching_modules.IsEmpty())
4140dda28197Spatrick       target->GetImages().FindModules(module_spec, matching_modules);
4141061da546Spatrick 
4142dda28197Spatrick     while (matching_modules.IsEmpty()) {
4143061da546Spatrick       ConstString filename_no_extension(
4144061da546Spatrick           module_spec.GetFileSpec().GetFileNameStrippingExtension());
4145061da546Spatrick       // Empty string returned, let's bail
4146061da546Spatrick       if (!filename_no_extension)
4147061da546Spatrick         break;
4148061da546Spatrick 
4149061da546Spatrick       // Check if there was no extension to strip and the basename is the same
4150061da546Spatrick       if (filename_no_extension == module_spec.GetFileSpec().GetFilename())
4151061da546Spatrick         break;
4152061da546Spatrick 
4153061da546Spatrick       // Replace basename with one fewer extension
4154*f6aab3d8Srobert       module_spec.GetFileSpec().SetFilename(filename_no_extension);
4155dda28197Spatrick       target->GetImages().FindModules(module_spec, matching_modules);
4156061da546Spatrick     }
4157061da546Spatrick 
4158dda28197Spatrick     if (matching_modules.GetSize() > 1) {
4159061da546Spatrick       result.AppendErrorWithFormat("multiple modules match symbol file '%s', "
4160061da546Spatrick                                    "use the --uuid option to resolve the "
4161061da546Spatrick                                    "ambiguity.\n",
4162061da546Spatrick                                    symfile_path);
4163dda28197Spatrick       return false;
4164dda28197Spatrick     }
4165dda28197Spatrick 
4166dda28197Spatrick     if (matching_modules.GetSize() == 1) {
4167dda28197Spatrick       ModuleSP module_sp(matching_modules.GetModuleAtIndex(0));
4168061da546Spatrick 
4169061da546Spatrick       // The module has not yet created its symbol vendor, we can just give
4170061da546Spatrick       // the existing target module the symfile path to use for when it
4171061da546Spatrick       // decides to create it!
4172061da546Spatrick       module_sp->SetSymbolFileFileSpec(symbol_fspec);
4173061da546Spatrick 
4174061da546Spatrick       SymbolFile *symbol_file =
4175061da546Spatrick           module_sp->GetSymbolFile(true, &result.GetErrorStream());
4176061da546Spatrick       if (symbol_file) {
4177061da546Spatrick         ObjectFile *object_file = symbol_file->GetObjectFile();
4178061da546Spatrick         if (object_file && object_file->GetFileSpec() == symbol_fspec) {
4179061da546Spatrick           // Provide feedback that the symfile has been successfully added.
4180061da546Spatrick           const FileSpec &module_fs = module_sp->GetFileSpec();
4181061da546Spatrick           result.AppendMessageWithFormat(
4182061da546Spatrick               "symbol file '%s' has been added to '%s'\n", symfile_path,
4183061da546Spatrick               module_fs.GetPath().c_str());
4184061da546Spatrick 
4185061da546Spatrick           // Let clients know something changed in the module if it is
4186061da546Spatrick           // currently loaded
4187061da546Spatrick           ModuleList module_list;
4188061da546Spatrick           module_list.Append(module_sp);
4189061da546Spatrick           target->SymbolsDidLoad(module_list);
4190061da546Spatrick 
4191061da546Spatrick           // Make sure we load any scripting resources that may be embedded
4192061da546Spatrick           // in the debug info files in case the platform supports that.
4193061da546Spatrick           Status error;
4194061da546Spatrick           StreamString feedback_stream;
4195061da546Spatrick           module_sp->LoadScriptingResourceInTarget(target, error,
4196061da546Spatrick                                                    &feedback_stream);
4197061da546Spatrick           if (error.Fail() && error.AsCString())
4198061da546Spatrick             result.AppendWarningWithFormat(
4199061da546Spatrick                 "unable to load scripting data for module %s - error "
4200061da546Spatrick                 "reported was %s",
4201061da546Spatrick                 module_sp->GetFileSpec()
4202061da546Spatrick                     .GetFileNameStrippingExtension()
4203061da546Spatrick                     .GetCString(),
4204061da546Spatrick                 error.AsCString());
4205061da546Spatrick           else if (feedback_stream.GetSize())
4206dda28197Spatrick             result.AppendWarning(feedback_stream.GetData());
4207061da546Spatrick 
4208061da546Spatrick           flush = true;
4209061da546Spatrick           result.SetStatus(eReturnStatusSuccessFinishResult);
4210061da546Spatrick           return true;
4211061da546Spatrick         }
4212061da546Spatrick       }
4213061da546Spatrick       // Clear the symbol file spec if anything went wrong
4214061da546Spatrick       module_sp->SetSymbolFileFileSpec(FileSpec());
4215061da546Spatrick     }
4216061da546Spatrick 
4217061da546Spatrick     StreamString ss_symfile_uuid;
4218061da546Spatrick     if (module_spec.GetUUID().IsValid()) {
4219061da546Spatrick       ss_symfile_uuid << " (";
4220061da546Spatrick       module_spec.GetUUID().Dump(&ss_symfile_uuid);
4221061da546Spatrick       ss_symfile_uuid << ')';
4222061da546Spatrick     }
4223061da546Spatrick     result.AppendErrorWithFormat(
4224061da546Spatrick         "symbol file '%s'%s does not match any existing module%s\n",
4225061da546Spatrick         symfile_path, ss_symfile_uuid.GetData(),
4226dda28197Spatrick         !llvm::sys::fs::is_regular_file(symbol_fspec.GetPath())
4227061da546Spatrick             ? "\n       please specify the full path to the symbol file"
4228061da546Spatrick             : "");
4229061da546Spatrick     return false;
4230061da546Spatrick   }
4231061da546Spatrick 
DownloadObjectAndSymbolFile(ModuleSpec & module_spec,CommandReturnObject & result,bool & flush)4232*f6aab3d8Srobert   bool DownloadObjectAndSymbolFile(ModuleSpec &module_spec,
4233*f6aab3d8Srobert                                    CommandReturnObject &result, bool &flush) {
4234*f6aab3d8Srobert     Status error;
4235*f6aab3d8Srobert     if (Symbols::DownloadObjectAndSymbolFile(module_spec, error)) {
4236*f6aab3d8Srobert       if (module_spec.GetSymbolFileSpec())
4237*f6aab3d8Srobert         return AddModuleSymbols(m_exe_ctx.GetTargetPtr(), module_spec, flush,
4238*f6aab3d8Srobert                                 result);
4239*f6aab3d8Srobert     } else {
4240*f6aab3d8Srobert       result.SetError(error);
4241*f6aab3d8Srobert     }
4242*f6aab3d8Srobert     return false;
4243*f6aab3d8Srobert   }
4244*f6aab3d8Srobert 
AddSymbolsForUUID(CommandReturnObject & result,bool & flush)4245*f6aab3d8Srobert   bool AddSymbolsForUUID(CommandReturnObject &result, bool &flush) {
4246*f6aab3d8Srobert     assert(m_uuid_option_group.GetOptionValue().OptionWasSet());
4247*f6aab3d8Srobert 
4248*f6aab3d8Srobert     ModuleSpec module_spec;
4249*f6aab3d8Srobert     module_spec.GetUUID() =
4250*f6aab3d8Srobert         m_uuid_option_group.GetOptionValue().GetCurrentValue();
4251*f6aab3d8Srobert 
4252*f6aab3d8Srobert     if (!DownloadObjectAndSymbolFile(module_spec, result, flush)) {
4253*f6aab3d8Srobert       StreamString error_strm;
4254*f6aab3d8Srobert       error_strm.PutCString("unable to find debug symbols for UUID ");
4255*f6aab3d8Srobert       module_spec.GetUUID().Dump(&error_strm);
4256*f6aab3d8Srobert       result.AppendError(error_strm.GetString());
4257*f6aab3d8Srobert       return false;
4258*f6aab3d8Srobert     }
4259*f6aab3d8Srobert 
4260*f6aab3d8Srobert     return true;
4261*f6aab3d8Srobert   }
4262*f6aab3d8Srobert 
AddSymbolsForFile(CommandReturnObject & result,bool & flush)4263*f6aab3d8Srobert   bool AddSymbolsForFile(CommandReturnObject &result, bool &flush) {
4264*f6aab3d8Srobert     assert(m_file_option.GetOptionValue().OptionWasSet());
4265*f6aab3d8Srobert 
4266*f6aab3d8Srobert     ModuleSpec module_spec;
4267*f6aab3d8Srobert     module_spec.GetFileSpec() =
4268*f6aab3d8Srobert         m_file_option.GetOptionValue().GetCurrentValue();
4269*f6aab3d8Srobert 
4270*f6aab3d8Srobert     Target *target = m_exe_ctx.GetTargetPtr();
4271*f6aab3d8Srobert     ModuleSP module_sp(target->GetImages().FindFirstModule(module_spec));
4272*f6aab3d8Srobert     if (module_sp) {
4273*f6aab3d8Srobert       module_spec.GetFileSpec() = module_sp->GetFileSpec();
4274*f6aab3d8Srobert       module_spec.GetPlatformFileSpec() = module_sp->GetPlatformFileSpec();
4275*f6aab3d8Srobert       module_spec.GetUUID() = module_sp->GetUUID();
4276*f6aab3d8Srobert       module_spec.GetArchitecture() = module_sp->GetArchitecture();
4277*f6aab3d8Srobert     } else {
4278*f6aab3d8Srobert       module_spec.GetArchitecture() = target->GetArchitecture();
4279*f6aab3d8Srobert     }
4280*f6aab3d8Srobert 
4281*f6aab3d8Srobert     if (!DownloadObjectAndSymbolFile(module_spec, result, flush)) {
4282*f6aab3d8Srobert       StreamString error_strm;
4283*f6aab3d8Srobert       error_strm.PutCString(
4284*f6aab3d8Srobert           "unable to find debug symbols for the executable file ");
4285*f6aab3d8Srobert       error_strm << module_spec.GetFileSpec();
4286*f6aab3d8Srobert       result.AppendError(error_strm.GetString());
4287*f6aab3d8Srobert       return false;
4288*f6aab3d8Srobert     }
4289*f6aab3d8Srobert 
4290*f6aab3d8Srobert     return true;
4291*f6aab3d8Srobert   }
4292*f6aab3d8Srobert 
AddSymbolsForFrame(CommandReturnObject & result,bool & flush)4293*f6aab3d8Srobert   bool AddSymbolsForFrame(CommandReturnObject &result, bool &flush) {
4294*f6aab3d8Srobert     assert(m_current_frame_option.GetOptionValue().OptionWasSet());
4295*f6aab3d8Srobert 
4296*f6aab3d8Srobert     Process *process = m_exe_ctx.GetProcessPtr();
4297*f6aab3d8Srobert     if (!process) {
4298*f6aab3d8Srobert       result.AppendError(
4299*f6aab3d8Srobert           "a process must exist in order to use the --frame option");
4300*f6aab3d8Srobert       return false;
4301*f6aab3d8Srobert     }
4302*f6aab3d8Srobert 
4303*f6aab3d8Srobert     const StateType process_state = process->GetState();
4304*f6aab3d8Srobert     if (!StateIsStoppedState(process_state, true)) {
4305*f6aab3d8Srobert       result.AppendErrorWithFormat("process is not stopped: %s",
4306*f6aab3d8Srobert                                    StateAsCString(process_state));
4307*f6aab3d8Srobert       return false;
4308*f6aab3d8Srobert     }
4309*f6aab3d8Srobert 
4310*f6aab3d8Srobert     StackFrame *frame = m_exe_ctx.GetFramePtr();
4311*f6aab3d8Srobert     if (!frame) {
4312*f6aab3d8Srobert       result.AppendError("invalid current frame");
4313*f6aab3d8Srobert       return false;
4314*f6aab3d8Srobert     }
4315*f6aab3d8Srobert 
4316*f6aab3d8Srobert     ModuleSP frame_module_sp(
4317*f6aab3d8Srobert         frame->GetSymbolContext(eSymbolContextModule).module_sp);
4318*f6aab3d8Srobert     if (!frame_module_sp) {
4319*f6aab3d8Srobert       result.AppendError("frame has no module");
4320*f6aab3d8Srobert       return false;
4321*f6aab3d8Srobert     }
4322*f6aab3d8Srobert 
4323*f6aab3d8Srobert     ModuleSpec module_spec;
4324*f6aab3d8Srobert     module_spec.GetUUID() = frame_module_sp->GetUUID();
4325*f6aab3d8Srobert 
4326*f6aab3d8Srobert     if (FileSystem::Instance().Exists(frame_module_sp->GetPlatformFileSpec())) {
4327*f6aab3d8Srobert       module_spec.GetArchitecture() = frame_module_sp->GetArchitecture();
4328*f6aab3d8Srobert       module_spec.GetFileSpec() = frame_module_sp->GetPlatformFileSpec();
4329*f6aab3d8Srobert     }
4330*f6aab3d8Srobert 
4331*f6aab3d8Srobert     if (!DownloadObjectAndSymbolFile(module_spec, result, flush)) {
4332*f6aab3d8Srobert       result.AppendError("unable to find debug symbols for the current frame");
4333*f6aab3d8Srobert       return false;
4334*f6aab3d8Srobert     }
4335*f6aab3d8Srobert 
4336*f6aab3d8Srobert     return true;
4337*f6aab3d8Srobert   }
4338*f6aab3d8Srobert 
AddSymbolsForStack(CommandReturnObject & result,bool & flush)4339*f6aab3d8Srobert   bool AddSymbolsForStack(CommandReturnObject &result, bool &flush) {
4340*f6aab3d8Srobert     assert(m_current_stack_option.GetOptionValue().OptionWasSet());
4341*f6aab3d8Srobert 
4342*f6aab3d8Srobert     Process *process = m_exe_ctx.GetProcessPtr();
4343*f6aab3d8Srobert     if (!process) {
4344*f6aab3d8Srobert       result.AppendError(
4345*f6aab3d8Srobert           "a process must exist in order to use the --stack option");
4346*f6aab3d8Srobert       return false;
4347*f6aab3d8Srobert     }
4348*f6aab3d8Srobert 
4349*f6aab3d8Srobert     const StateType process_state = process->GetState();
4350*f6aab3d8Srobert     if (!StateIsStoppedState(process_state, true)) {
4351*f6aab3d8Srobert       result.AppendErrorWithFormat("process is not stopped: %s",
4352*f6aab3d8Srobert                                    StateAsCString(process_state));
4353*f6aab3d8Srobert       return false;
4354*f6aab3d8Srobert     }
4355*f6aab3d8Srobert 
4356*f6aab3d8Srobert     Thread *thread = m_exe_ctx.GetThreadPtr();
4357*f6aab3d8Srobert     if (!thread) {
4358*f6aab3d8Srobert       result.AppendError("invalid current thread");
4359*f6aab3d8Srobert       return false;
4360*f6aab3d8Srobert     }
4361*f6aab3d8Srobert 
4362*f6aab3d8Srobert     bool symbols_found = false;
4363*f6aab3d8Srobert     uint32_t frame_count = thread->GetStackFrameCount();
4364*f6aab3d8Srobert     for (uint32_t i = 0; i < frame_count; ++i) {
4365*f6aab3d8Srobert       lldb::StackFrameSP frame_sp = thread->GetStackFrameAtIndex(i);
4366*f6aab3d8Srobert 
4367*f6aab3d8Srobert       ModuleSP frame_module_sp(
4368*f6aab3d8Srobert           frame_sp->GetSymbolContext(eSymbolContextModule).module_sp);
4369*f6aab3d8Srobert       if (!frame_module_sp)
4370*f6aab3d8Srobert         continue;
4371*f6aab3d8Srobert 
4372*f6aab3d8Srobert       ModuleSpec module_spec;
4373*f6aab3d8Srobert       module_spec.GetUUID() = frame_module_sp->GetUUID();
4374*f6aab3d8Srobert 
4375*f6aab3d8Srobert       if (FileSystem::Instance().Exists(
4376*f6aab3d8Srobert               frame_module_sp->GetPlatformFileSpec())) {
4377*f6aab3d8Srobert         module_spec.GetArchitecture() = frame_module_sp->GetArchitecture();
4378*f6aab3d8Srobert         module_spec.GetFileSpec() = frame_module_sp->GetPlatformFileSpec();
4379*f6aab3d8Srobert       }
4380*f6aab3d8Srobert 
4381*f6aab3d8Srobert       bool current_frame_flush = false;
4382*f6aab3d8Srobert       if (DownloadObjectAndSymbolFile(module_spec, result, current_frame_flush))
4383*f6aab3d8Srobert         symbols_found = true;
4384*f6aab3d8Srobert       flush |= current_frame_flush;
4385*f6aab3d8Srobert     }
4386*f6aab3d8Srobert 
4387*f6aab3d8Srobert     if (!symbols_found) {
4388*f6aab3d8Srobert       result.AppendError(
4389*f6aab3d8Srobert           "unable to find debug symbols in the current call stack");
4390*f6aab3d8Srobert       return false;
4391*f6aab3d8Srobert     }
4392*f6aab3d8Srobert 
4393*f6aab3d8Srobert     return true;
4394*f6aab3d8Srobert   }
4395*f6aab3d8Srobert 
DoExecute(Args & args,CommandReturnObject & result)4396061da546Spatrick   bool DoExecute(Args &args, CommandReturnObject &result) override {
4397061da546Spatrick     Target *target = m_exe_ctx.GetTargetPtr();
4398061da546Spatrick     result.SetStatus(eReturnStatusFailed);
4399061da546Spatrick     bool flush = false;
4400061da546Spatrick     ModuleSpec module_spec;
4401061da546Spatrick     const bool uuid_option_set =
4402061da546Spatrick         m_uuid_option_group.GetOptionValue().OptionWasSet();
4403061da546Spatrick     const bool file_option_set = m_file_option.GetOptionValue().OptionWasSet();
4404061da546Spatrick     const bool frame_option_set =
4405061da546Spatrick         m_current_frame_option.GetOptionValue().OptionWasSet();
4406*f6aab3d8Srobert     const bool stack_option_set =
4407*f6aab3d8Srobert         m_current_stack_option.GetOptionValue().OptionWasSet();
4408061da546Spatrick     const size_t argc = args.GetArgumentCount();
4409061da546Spatrick 
4410061da546Spatrick     if (argc == 0) {
4411*f6aab3d8Srobert       if (uuid_option_set)
4412*f6aab3d8Srobert         AddSymbolsForUUID(result, flush);
4413*f6aab3d8Srobert       else if (file_option_set)
4414*f6aab3d8Srobert         AddSymbolsForFile(result, flush);
4415*f6aab3d8Srobert       else if (frame_option_set)
4416*f6aab3d8Srobert         AddSymbolsForFrame(result, flush);
4417*f6aab3d8Srobert       else if (stack_option_set)
4418*f6aab3d8Srobert         AddSymbolsForStack(result, flush);
4419*f6aab3d8Srobert       else
4420061da546Spatrick         result.AppendError("one or more symbol file paths must be specified, "
4421061da546Spatrick                            "or options must be specified");
4422061da546Spatrick     } else {
4423061da546Spatrick       if (uuid_option_set) {
4424061da546Spatrick         result.AppendError("specify either one or more paths to symbol files "
4425061da546Spatrick                            "or use the --uuid option without arguments");
4426061da546Spatrick       } else if (frame_option_set) {
4427061da546Spatrick         result.AppendError("specify either one or more paths to symbol files "
4428061da546Spatrick                            "or use the --frame option without arguments");
4429061da546Spatrick       } else if (file_option_set && argc > 1) {
4430061da546Spatrick         result.AppendError("specify at most one symbol file path when "
4431061da546Spatrick                            "--shlib option is set");
4432061da546Spatrick       } else {
4433061da546Spatrick         PlatformSP platform_sp(target->GetPlatform());
4434061da546Spatrick 
4435061da546Spatrick         for (auto &entry : args.entries()) {
4436061da546Spatrick           if (!entry.ref().empty()) {
4437061da546Spatrick             auto &symbol_file_spec = module_spec.GetSymbolFileSpec();
4438061da546Spatrick             symbol_file_spec.SetFile(entry.ref(), FileSpec::Style::native);
4439061da546Spatrick             FileSystem::Instance().Resolve(symbol_file_spec);
4440061da546Spatrick             if (file_option_set) {
4441061da546Spatrick               module_spec.GetFileSpec() =
4442061da546Spatrick                   m_file_option.GetOptionValue().GetCurrentValue();
4443061da546Spatrick             }
4444061da546Spatrick             if (platform_sp) {
4445061da546Spatrick               FileSpec symfile_spec;
4446061da546Spatrick               if (platform_sp
4447061da546Spatrick                       ->ResolveSymbolFile(*target, module_spec, symfile_spec)
4448061da546Spatrick                       .Success())
4449061da546Spatrick                 module_spec.GetSymbolFileSpec() = symfile_spec;
4450061da546Spatrick             }
4451061da546Spatrick 
4452061da546Spatrick             bool symfile_exists =
4453061da546Spatrick                 FileSystem::Instance().Exists(module_spec.GetSymbolFileSpec());
4454061da546Spatrick 
4455061da546Spatrick             if (symfile_exists) {
4456061da546Spatrick               if (!AddModuleSymbols(target, module_spec, flush, result))
4457061da546Spatrick                 break;
4458061da546Spatrick             } else {
4459061da546Spatrick               std::string resolved_symfile_path =
4460061da546Spatrick                   module_spec.GetSymbolFileSpec().GetPath();
4461061da546Spatrick               if (resolved_symfile_path != entry.ref()) {
4462061da546Spatrick                 result.AppendErrorWithFormat(
4463061da546Spatrick                     "invalid module path '%s' with resolved path '%s'\n",
4464061da546Spatrick                     entry.c_str(), resolved_symfile_path.c_str());
4465061da546Spatrick                 break;
4466061da546Spatrick               }
4467061da546Spatrick               result.AppendErrorWithFormat("invalid module path '%s'\n",
4468061da546Spatrick                                            entry.c_str());
4469061da546Spatrick               break;
4470061da546Spatrick             }
4471061da546Spatrick           }
4472061da546Spatrick         }
4473061da546Spatrick       }
4474061da546Spatrick     }
4475061da546Spatrick 
4476061da546Spatrick     if (flush) {
4477061da546Spatrick       Process *process = m_exe_ctx.GetProcessPtr();
4478061da546Spatrick       if (process)
4479061da546Spatrick         process->Flush();
4480061da546Spatrick     }
4481061da546Spatrick     return result.Succeeded();
4482061da546Spatrick   }
4483061da546Spatrick 
4484061da546Spatrick   OptionGroupOptions m_option_group;
4485061da546Spatrick   OptionGroupUUID m_uuid_option_group;
4486061da546Spatrick   OptionGroupFile m_file_option;
4487061da546Spatrick   OptionGroupBoolean m_current_frame_option;
4488*f6aab3d8Srobert   OptionGroupBoolean m_current_stack_option;
4489061da546Spatrick };
4490061da546Spatrick 
4491061da546Spatrick #pragma mark CommandObjectTargetSymbols
4492061da546Spatrick 
4493061da546Spatrick // CommandObjectTargetSymbols
4494061da546Spatrick 
4495061da546Spatrick class CommandObjectTargetSymbols : public CommandObjectMultiword {
4496061da546Spatrick public:
4497061da546Spatrick   // Constructors and Destructors
CommandObjectTargetSymbols(CommandInterpreter & interpreter)4498061da546Spatrick   CommandObjectTargetSymbols(CommandInterpreter &interpreter)
4499061da546Spatrick       : CommandObjectMultiword(
4500061da546Spatrick             interpreter, "target symbols",
4501061da546Spatrick             "Commands for adding and managing debug symbol files.",
4502061da546Spatrick             "target symbols <sub-command> ...") {
4503061da546Spatrick     LoadSubCommand(
4504061da546Spatrick         "add", CommandObjectSP(new CommandObjectTargetSymbolsAdd(interpreter)));
4505061da546Spatrick   }
4506061da546Spatrick 
4507061da546Spatrick   ~CommandObjectTargetSymbols() override = default;
4508061da546Spatrick 
4509061da546Spatrick private:
4510061da546Spatrick   // For CommandObjectTargetModules only
4511dda28197Spatrick   CommandObjectTargetSymbols(const CommandObjectTargetSymbols &) = delete;
4512dda28197Spatrick   const CommandObjectTargetSymbols &
4513dda28197Spatrick   operator=(const CommandObjectTargetSymbols &) = delete;
4514061da546Spatrick };
4515061da546Spatrick 
4516061da546Spatrick #pragma mark CommandObjectTargetStopHookAdd
4517061da546Spatrick 
4518061da546Spatrick // CommandObjectTargetStopHookAdd
4519061da546Spatrick #define LLDB_OPTIONS_target_stop_hook_add
4520061da546Spatrick #include "CommandOptions.inc"
4521061da546Spatrick 
4522061da546Spatrick class CommandObjectTargetStopHookAdd : public CommandObjectParsed,
4523061da546Spatrick                                        public IOHandlerDelegateMultiline {
4524061da546Spatrick public:
4525be691f3bSpatrick   class CommandOptions : public OptionGroup {
4526061da546Spatrick   public:
CommandOptions()4527*f6aab3d8Srobert     CommandOptions() : m_line_end(UINT_MAX) {}
4528061da546Spatrick 
4529061da546Spatrick     ~CommandOptions() override = default;
4530061da546Spatrick 
GetDefinitions()4531061da546Spatrick     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
4532*f6aab3d8Srobert       return llvm::ArrayRef(g_target_stop_hook_add_options);
4533061da546Spatrick     }
4534061da546Spatrick 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)4535061da546Spatrick     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
4536061da546Spatrick                           ExecutionContext *execution_context) override {
4537061da546Spatrick       Status error;
4538be691f3bSpatrick       const int short_option =
4539be691f3bSpatrick           g_target_stop_hook_add_options[option_idx].short_option;
4540061da546Spatrick 
4541061da546Spatrick       switch (short_option) {
4542061da546Spatrick       case 'c':
4543dda28197Spatrick         m_class_name = std::string(option_arg);
4544061da546Spatrick         m_sym_ctx_specified = true;
4545061da546Spatrick         break;
4546061da546Spatrick 
4547061da546Spatrick       case 'e':
4548061da546Spatrick         if (option_arg.getAsInteger(0, m_line_end)) {
4549061da546Spatrick           error.SetErrorStringWithFormat("invalid end line number: \"%s\"",
4550061da546Spatrick                                          option_arg.str().c_str());
4551061da546Spatrick           break;
4552061da546Spatrick         }
4553061da546Spatrick         m_sym_ctx_specified = true;
4554061da546Spatrick         break;
4555061da546Spatrick 
4556061da546Spatrick       case 'G': {
4557061da546Spatrick         bool value, success;
4558061da546Spatrick         value = OptionArgParser::ToBoolean(option_arg, false, &success);
4559061da546Spatrick         if (success) {
4560061da546Spatrick           m_auto_continue = value;
4561061da546Spatrick         } else
4562061da546Spatrick           error.SetErrorStringWithFormat(
4563061da546Spatrick               "invalid boolean value '%s' passed for -G option",
4564061da546Spatrick               option_arg.str().c_str());
4565061da546Spatrick       } break;
4566061da546Spatrick       case 'l':
4567061da546Spatrick         if (option_arg.getAsInteger(0, m_line_start)) {
4568061da546Spatrick           error.SetErrorStringWithFormat("invalid start line number: \"%s\"",
4569061da546Spatrick                                          option_arg.str().c_str());
4570061da546Spatrick           break;
4571061da546Spatrick         }
4572061da546Spatrick         m_sym_ctx_specified = true;
4573061da546Spatrick         break;
4574061da546Spatrick 
4575061da546Spatrick       case 'i':
4576061da546Spatrick         m_no_inlines = true;
4577061da546Spatrick         break;
4578061da546Spatrick 
4579061da546Spatrick       case 'n':
4580dda28197Spatrick         m_function_name = std::string(option_arg);
4581061da546Spatrick         m_func_name_type_mask |= eFunctionNameTypeAuto;
4582061da546Spatrick         m_sym_ctx_specified = true;
4583061da546Spatrick         break;
4584061da546Spatrick 
4585061da546Spatrick       case 'f':
4586dda28197Spatrick         m_file_name = std::string(option_arg);
4587061da546Spatrick         m_sym_ctx_specified = true;
4588061da546Spatrick         break;
4589061da546Spatrick 
4590061da546Spatrick       case 's':
4591dda28197Spatrick         m_module_name = std::string(option_arg);
4592061da546Spatrick         m_sym_ctx_specified = true;
4593061da546Spatrick         break;
4594061da546Spatrick 
4595061da546Spatrick       case 't':
4596061da546Spatrick         if (option_arg.getAsInteger(0, m_thread_id))
4597061da546Spatrick           error.SetErrorStringWithFormat("invalid thread id string '%s'",
4598061da546Spatrick                                          option_arg.str().c_str());
4599061da546Spatrick         m_thread_specified = true;
4600061da546Spatrick         break;
4601061da546Spatrick 
4602061da546Spatrick       case 'T':
4603dda28197Spatrick         m_thread_name = std::string(option_arg);
4604061da546Spatrick         m_thread_specified = true;
4605061da546Spatrick         break;
4606061da546Spatrick 
4607061da546Spatrick       case 'q':
4608dda28197Spatrick         m_queue_name = std::string(option_arg);
4609061da546Spatrick         m_thread_specified = true;
4610061da546Spatrick         break;
4611061da546Spatrick 
4612061da546Spatrick       case 'x':
4613061da546Spatrick         if (option_arg.getAsInteger(0, m_thread_index))
4614061da546Spatrick           error.SetErrorStringWithFormat("invalid thread index string '%s'",
4615061da546Spatrick                                          option_arg.str().c_str());
4616061da546Spatrick         m_thread_specified = true;
4617061da546Spatrick         break;
4618061da546Spatrick 
4619061da546Spatrick       case 'o':
4620061da546Spatrick         m_use_one_liner = true;
4621dda28197Spatrick         m_one_liner.push_back(std::string(option_arg));
4622061da546Spatrick         break;
4623061da546Spatrick 
4624061da546Spatrick       default:
4625061da546Spatrick         llvm_unreachable("Unimplemented option");
4626061da546Spatrick       }
4627061da546Spatrick       return error;
4628061da546Spatrick     }
4629061da546Spatrick 
OptionParsingStarting(ExecutionContext * execution_context)4630061da546Spatrick     void OptionParsingStarting(ExecutionContext *execution_context) override {
4631061da546Spatrick       m_class_name.clear();
4632061da546Spatrick       m_function_name.clear();
4633061da546Spatrick       m_line_start = 0;
4634*f6aab3d8Srobert       m_line_end = LLDB_INVALID_LINE_NUMBER;
4635061da546Spatrick       m_file_name.clear();
4636061da546Spatrick       m_module_name.clear();
4637061da546Spatrick       m_func_name_type_mask = eFunctionNameTypeAuto;
4638061da546Spatrick       m_thread_id = LLDB_INVALID_THREAD_ID;
4639061da546Spatrick       m_thread_index = UINT32_MAX;
4640061da546Spatrick       m_thread_name.clear();
4641061da546Spatrick       m_queue_name.clear();
4642061da546Spatrick 
4643061da546Spatrick       m_no_inlines = false;
4644061da546Spatrick       m_sym_ctx_specified = false;
4645061da546Spatrick       m_thread_specified = false;
4646061da546Spatrick 
4647061da546Spatrick       m_use_one_liner = false;
4648061da546Spatrick       m_one_liner.clear();
4649061da546Spatrick       m_auto_continue = false;
4650061da546Spatrick     }
4651061da546Spatrick 
4652061da546Spatrick     std::string m_class_name;
4653061da546Spatrick     std::string m_function_name;
4654be691f3bSpatrick     uint32_t m_line_start = 0;
4655*f6aab3d8Srobert     uint32_t m_line_end = LLDB_INVALID_LINE_NUMBER;
4656061da546Spatrick     std::string m_file_name;
4657061da546Spatrick     std::string m_module_name;
4658be691f3bSpatrick     uint32_t m_func_name_type_mask =
4659be691f3bSpatrick         eFunctionNameTypeAuto; // A pick from lldb::FunctionNameType.
4660*f6aab3d8Srobert     lldb::tid_t m_thread_id = LLDB_INVALID_THREAD_ID;
4661*f6aab3d8Srobert     uint32_t m_thread_index = UINT32_MAX;
4662061da546Spatrick     std::string m_thread_name;
4663061da546Spatrick     std::string m_queue_name;
4664be691f3bSpatrick     bool m_sym_ctx_specified = false;
4665*f6aab3d8Srobert     bool m_no_inlines = false;
4666be691f3bSpatrick     bool m_thread_specified = false;
4667061da546Spatrick     // Instance variables to hold the values for one_liner options.
4668be691f3bSpatrick     bool m_use_one_liner = false;
4669061da546Spatrick     std::vector<std::string> m_one_liner;
4670be691f3bSpatrick 
4671*f6aab3d8Srobert     bool m_auto_continue = false;
4672061da546Spatrick   };
4673061da546Spatrick 
CommandObjectTargetStopHookAdd(CommandInterpreter & interpreter)4674061da546Spatrick   CommandObjectTargetStopHookAdd(CommandInterpreter &interpreter)
4675061da546Spatrick       : CommandObjectParsed(interpreter, "target stop-hook add",
4676be691f3bSpatrick                             "Add a hook to be executed when the target stops."
4677be691f3bSpatrick                             "The hook can either be a list of commands or an "
4678be691f3bSpatrick                             "appropriately defined Python class.  You can also "
4679be691f3bSpatrick                             "add filters so the hook only runs a certain stop "
4680be691f3bSpatrick                             "points.",
4681061da546Spatrick                             "target stop-hook add"),
4682061da546Spatrick         IOHandlerDelegateMultiline("DONE",
4683061da546Spatrick                                    IOHandlerDelegate::Completion::LLDBCommand),
4684*f6aab3d8Srobert         m_python_class_options("scripted stop-hook", true, 'P') {
4685be691f3bSpatrick     SetHelpLong(
4686be691f3bSpatrick         R"(
4687be691f3bSpatrick Command Based stop-hooks:
4688be691f3bSpatrick -------------------------
4689be691f3bSpatrick   Stop hooks can run a list of lldb commands by providing one or more
4690be691f3bSpatrick   --one-line-command options.  The commands will get run in the order they are
4691be691f3bSpatrick   added.  Or you can provide no commands, in which case you will enter a
4692be691f3bSpatrick   command editor where you can enter the commands to be run.
4693be691f3bSpatrick 
4694be691f3bSpatrick Python Based Stop Hooks:
4695be691f3bSpatrick ------------------------
4696be691f3bSpatrick   Stop hooks can be implemented with a suitably defined Python class, whose name
4697be691f3bSpatrick   is passed in the --python-class option.
4698be691f3bSpatrick 
4699be691f3bSpatrick   When the stop hook is added, the class is initialized by calling:
4700be691f3bSpatrick 
4701be691f3bSpatrick     def __init__(self, target, extra_args, internal_dict):
4702be691f3bSpatrick 
4703be691f3bSpatrick     target: The target that the stop hook is being added to.
4704be691f3bSpatrick     extra_args: An SBStructuredData Dictionary filled with the -key -value
4705be691f3bSpatrick                 option pairs passed to the command.
4706be691f3bSpatrick     dict: An implementation detail provided by lldb.
4707be691f3bSpatrick 
4708be691f3bSpatrick   Then when the stop-hook triggers, lldb will run the 'handle_stop' method.
4709be691f3bSpatrick   The method has the signature:
4710be691f3bSpatrick 
4711be691f3bSpatrick     def handle_stop(self, exe_ctx, stream):
4712be691f3bSpatrick 
4713be691f3bSpatrick     exe_ctx: An SBExecutionContext for the thread that has stopped.
4714be691f3bSpatrick     stream: An SBStream, anything written to this stream will be printed in the
4715be691f3bSpatrick             the stop message when the process stops.
4716be691f3bSpatrick 
4717be691f3bSpatrick     Return Value: The method returns "should_stop".  If should_stop is false
4718be691f3bSpatrick                   from all the stop hook executions on threads that stopped
4719be691f3bSpatrick                   with a reason, then the process will continue.  Note that this
4720be691f3bSpatrick                   will happen only after all the stop hooks are run.
4721be691f3bSpatrick 
4722be691f3bSpatrick Filter Options:
4723be691f3bSpatrick ---------------
4724be691f3bSpatrick   Stop hooks can be set to always run, or to only run when the stopped thread
4725be691f3bSpatrick   matches the filter options passed on the command line.  The available filter
4726be691f3bSpatrick   options include a shared library or a thread or queue specification,
4727be691f3bSpatrick   a line range in a source file, a function name or a class name.
4728be691f3bSpatrick             )");
4729be691f3bSpatrick     m_all_options.Append(&m_python_class_options,
4730be691f3bSpatrick                          LLDB_OPT_SET_1 | LLDB_OPT_SET_2,
4731be691f3bSpatrick                          LLDB_OPT_SET_FROM_TO(4, 6));
4732be691f3bSpatrick     m_all_options.Append(&m_options);
4733be691f3bSpatrick     m_all_options.Finalize();
4734be691f3bSpatrick   }
4735061da546Spatrick 
4736061da546Spatrick   ~CommandObjectTargetStopHookAdd() override = default;
4737061da546Spatrick 
GetOptions()4738be691f3bSpatrick   Options *GetOptions() override { return &m_all_options; }
4739061da546Spatrick 
4740061da546Spatrick protected:
IOHandlerActivated(IOHandler & io_handler,bool interactive)4741061da546Spatrick   void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
4742061da546Spatrick     StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
4743061da546Spatrick     if (output_sp && interactive) {
4744061da546Spatrick       output_sp->PutCString(
4745061da546Spatrick           "Enter your stop hook command(s).  Type 'DONE' to end.\n");
4746061da546Spatrick       output_sp->Flush();
4747061da546Spatrick     }
4748061da546Spatrick   }
4749061da546Spatrick 
IOHandlerInputComplete(IOHandler & io_handler,std::string & line)4750061da546Spatrick   void IOHandlerInputComplete(IOHandler &io_handler,
4751061da546Spatrick                               std::string &line) override {
4752061da546Spatrick     if (m_stop_hook_sp) {
4753061da546Spatrick       if (line.empty()) {
4754061da546Spatrick         StreamFileSP error_sp(io_handler.GetErrorStreamFileSP());
4755061da546Spatrick         if (error_sp) {
4756061da546Spatrick           error_sp->Printf("error: stop hook #%" PRIu64
4757061da546Spatrick                            " aborted, no commands.\n",
4758061da546Spatrick                            m_stop_hook_sp->GetID());
4759061da546Spatrick           error_sp->Flush();
4760061da546Spatrick         }
4761061da546Spatrick         Target *target = GetDebugger().GetSelectedTarget().get();
4762be691f3bSpatrick         if (target) {
4763be691f3bSpatrick           target->UndoCreateStopHook(m_stop_hook_sp->GetID());
4764be691f3bSpatrick         }
4765061da546Spatrick       } else {
4766be691f3bSpatrick         // The IOHandler editor is only for command lines stop hooks:
4767be691f3bSpatrick         Target::StopHookCommandLine *hook_ptr =
4768be691f3bSpatrick             static_cast<Target::StopHookCommandLine *>(m_stop_hook_sp.get());
4769be691f3bSpatrick 
4770be691f3bSpatrick         hook_ptr->SetActionFromString(line);
4771061da546Spatrick         StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
4772061da546Spatrick         if (output_sp) {
4773061da546Spatrick           output_sp->Printf("Stop hook #%" PRIu64 " added.\n",
4774061da546Spatrick                             m_stop_hook_sp->GetID());
4775061da546Spatrick           output_sp->Flush();
4776061da546Spatrick         }
4777061da546Spatrick       }
4778061da546Spatrick       m_stop_hook_sp.reset();
4779061da546Spatrick     }
4780061da546Spatrick     io_handler.SetIsDone(true);
4781061da546Spatrick   }
4782061da546Spatrick 
DoExecute(Args & command,CommandReturnObject & result)4783061da546Spatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
4784061da546Spatrick     m_stop_hook_sp.reset();
4785061da546Spatrick 
4786061da546Spatrick     Target &target = GetSelectedOrDummyTarget();
4787be691f3bSpatrick     Target::StopHookSP new_hook_sp =
4788be691f3bSpatrick         target.CreateStopHook(m_python_class_options.GetName().empty() ?
4789be691f3bSpatrick                                Target::StopHook::StopHookKind::CommandBased
4790be691f3bSpatrick                                : Target::StopHook::StopHookKind::ScriptBased);
4791061da546Spatrick 
4792061da546Spatrick     //  First step, make the specifier.
4793061da546Spatrick     std::unique_ptr<SymbolContextSpecifier> specifier_up;
4794061da546Spatrick     if (m_options.m_sym_ctx_specified) {
4795dda28197Spatrick       specifier_up = std::make_unique<SymbolContextSpecifier>(
4796dda28197Spatrick           GetDebugger().GetSelectedTarget());
4797061da546Spatrick 
4798061da546Spatrick       if (!m_options.m_module_name.empty()) {
4799061da546Spatrick         specifier_up->AddSpecification(
4800061da546Spatrick             m_options.m_module_name.c_str(),
4801061da546Spatrick             SymbolContextSpecifier::eModuleSpecified);
4802061da546Spatrick       }
4803061da546Spatrick 
4804061da546Spatrick       if (!m_options.m_class_name.empty()) {
4805061da546Spatrick         specifier_up->AddSpecification(
4806061da546Spatrick             m_options.m_class_name.c_str(),
4807061da546Spatrick             SymbolContextSpecifier::eClassOrNamespaceSpecified);
4808061da546Spatrick       }
4809061da546Spatrick 
4810061da546Spatrick       if (!m_options.m_file_name.empty()) {
4811061da546Spatrick         specifier_up->AddSpecification(m_options.m_file_name.c_str(),
4812061da546Spatrick                                        SymbolContextSpecifier::eFileSpecified);
4813061da546Spatrick       }
4814061da546Spatrick 
4815061da546Spatrick       if (m_options.m_line_start != 0) {
4816061da546Spatrick         specifier_up->AddLineSpecification(
4817061da546Spatrick             m_options.m_line_start,
4818061da546Spatrick             SymbolContextSpecifier::eLineStartSpecified);
4819061da546Spatrick       }
4820061da546Spatrick 
4821061da546Spatrick       if (m_options.m_line_end != UINT_MAX) {
4822061da546Spatrick         specifier_up->AddLineSpecification(
4823061da546Spatrick             m_options.m_line_end, SymbolContextSpecifier::eLineEndSpecified);
4824061da546Spatrick       }
4825061da546Spatrick 
4826061da546Spatrick       if (!m_options.m_function_name.empty()) {
4827061da546Spatrick         specifier_up->AddSpecification(
4828061da546Spatrick             m_options.m_function_name.c_str(),
4829061da546Spatrick             SymbolContextSpecifier::eFunctionSpecified);
4830061da546Spatrick       }
4831061da546Spatrick     }
4832061da546Spatrick 
4833061da546Spatrick     if (specifier_up)
4834061da546Spatrick       new_hook_sp->SetSpecifier(specifier_up.release());
4835061da546Spatrick 
4836061da546Spatrick     // Next see if any of the thread options have been entered:
4837061da546Spatrick 
4838061da546Spatrick     if (m_options.m_thread_specified) {
4839061da546Spatrick       ThreadSpec *thread_spec = new ThreadSpec();
4840061da546Spatrick 
4841061da546Spatrick       if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID) {
4842061da546Spatrick         thread_spec->SetTID(m_options.m_thread_id);
4843061da546Spatrick       }
4844061da546Spatrick 
4845061da546Spatrick       if (m_options.m_thread_index != UINT32_MAX)
4846061da546Spatrick         thread_spec->SetIndex(m_options.m_thread_index);
4847061da546Spatrick 
4848061da546Spatrick       if (!m_options.m_thread_name.empty())
4849061da546Spatrick         thread_spec->SetName(m_options.m_thread_name.c_str());
4850061da546Spatrick 
4851061da546Spatrick       if (!m_options.m_queue_name.empty())
4852061da546Spatrick         thread_spec->SetQueueName(m_options.m_queue_name.c_str());
4853061da546Spatrick 
4854061da546Spatrick       new_hook_sp->SetThreadSpecifier(thread_spec);
4855061da546Spatrick     }
4856061da546Spatrick 
4857061da546Spatrick     new_hook_sp->SetAutoContinue(m_options.m_auto_continue);
4858061da546Spatrick     if (m_options.m_use_one_liner) {
4859be691f3bSpatrick       // This is a command line stop hook:
4860be691f3bSpatrick       Target::StopHookCommandLine *hook_ptr =
4861be691f3bSpatrick           static_cast<Target::StopHookCommandLine *>(new_hook_sp.get());
4862be691f3bSpatrick       hook_ptr->SetActionFromStrings(m_options.m_one_liner);
4863061da546Spatrick       result.AppendMessageWithFormat("Stop hook #%" PRIu64 " added.\n",
4864061da546Spatrick                                      new_hook_sp->GetID());
4865be691f3bSpatrick     } else if (!m_python_class_options.GetName().empty()) {
4866be691f3bSpatrick       // This is a scripted stop hook:
4867be691f3bSpatrick       Target::StopHookScripted *hook_ptr =
4868be691f3bSpatrick           static_cast<Target::StopHookScripted *>(new_hook_sp.get());
4869be691f3bSpatrick       Status error = hook_ptr->SetScriptCallback(
4870be691f3bSpatrick           m_python_class_options.GetName(),
4871be691f3bSpatrick           m_python_class_options.GetStructuredData());
4872be691f3bSpatrick       if (error.Success())
4873be691f3bSpatrick         result.AppendMessageWithFormat("Stop hook #%" PRIu64 " added.\n",
4874be691f3bSpatrick                                        new_hook_sp->GetID());
4875be691f3bSpatrick       else {
4876be691f3bSpatrick         // FIXME: Set the stop hook ID counter back.
4877be691f3bSpatrick         result.AppendErrorWithFormat("Couldn't add stop hook: %s",
4878be691f3bSpatrick                                      error.AsCString());
4879be691f3bSpatrick         target.UndoCreateStopHook(new_hook_sp->GetID());
4880be691f3bSpatrick         return false;
4881be691f3bSpatrick       }
4882061da546Spatrick     } else {
4883061da546Spatrick       m_stop_hook_sp = new_hook_sp;
4884061da546Spatrick       m_interpreter.GetLLDBCommandsFromIOHandler("> ",   // Prompt
4885061da546Spatrick                                                  *this); // IOHandlerDelegate
4886061da546Spatrick     }
4887061da546Spatrick     result.SetStatus(eReturnStatusSuccessFinishNoResult);
4888061da546Spatrick 
4889061da546Spatrick     return result.Succeeded();
4890061da546Spatrick   }
4891061da546Spatrick 
4892061da546Spatrick private:
4893061da546Spatrick   CommandOptions m_options;
4894be691f3bSpatrick   OptionGroupPythonClassWithDict m_python_class_options;
4895be691f3bSpatrick   OptionGroupOptions m_all_options;
4896be691f3bSpatrick 
4897061da546Spatrick   Target::StopHookSP m_stop_hook_sp;
4898061da546Spatrick };
4899061da546Spatrick 
4900061da546Spatrick #pragma mark CommandObjectTargetStopHookDelete
4901061da546Spatrick 
4902061da546Spatrick // CommandObjectTargetStopHookDelete
4903061da546Spatrick 
4904061da546Spatrick class CommandObjectTargetStopHookDelete : public CommandObjectParsed {
4905061da546Spatrick public:
CommandObjectTargetStopHookDelete(CommandInterpreter & interpreter)4906061da546Spatrick   CommandObjectTargetStopHookDelete(CommandInterpreter &interpreter)
4907061da546Spatrick       : CommandObjectParsed(interpreter, "target stop-hook delete",
4908061da546Spatrick                             "Delete a stop-hook.",
4909*f6aab3d8Srobert                             "target stop-hook delete [<idx>]") {
4910*f6aab3d8Srobert     CommandArgumentData hook_arg{eArgTypeStopHookID, eArgRepeatStar};
4911*f6aab3d8Srobert     m_arguments.push_back({hook_arg});
4912*f6aab3d8Srobert   }
4913061da546Spatrick 
4914061da546Spatrick   ~CommandObjectTargetStopHookDelete() override = default;
4915061da546Spatrick 
4916be691f3bSpatrick   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)4917be691f3bSpatrick   HandleArgumentCompletion(CompletionRequest &request,
4918be691f3bSpatrick                            OptionElementVector &opt_element_vector) override {
4919be691f3bSpatrick     CommandCompletions::InvokeCommonCompletionCallbacks(
4920be691f3bSpatrick         GetCommandInterpreter(), CommandCompletions::eStopHookIDCompletion,
4921be691f3bSpatrick         request, nullptr);
4922be691f3bSpatrick   }
4923be691f3bSpatrick 
4924061da546Spatrick protected:
DoExecute(Args & command,CommandReturnObject & result)4925061da546Spatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
4926061da546Spatrick     Target &target = GetSelectedOrDummyTarget();
4927061da546Spatrick     // FIXME: see if we can use the breakpoint id style parser?
4928061da546Spatrick     size_t num_args = command.GetArgumentCount();
4929061da546Spatrick     if (num_args == 0) {
4930061da546Spatrick       if (!m_interpreter.Confirm("Delete all stop hooks?", true)) {
4931061da546Spatrick         result.SetStatus(eReturnStatusFailed);
4932061da546Spatrick         return false;
4933061da546Spatrick       } else {
4934061da546Spatrick         target.RemoveAllStopHooks();
4935061da546Spatrick       }
4936061da546Spatrick     } else {
4937061da546Spatrick       for (size_t i = 0; i < num_args; i++) {
4938dda28197Spatrick         lldb::user_id_t user_id;
4939dda28197Spatrick         if (!llvm::to_integer(command.GetArgumentAtIndex(i), user_id)) {
4940061da546Spatrick           result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n",
4941061da546Spatrick                                        command.GetArgumentAtIndex(i));
4942061da546Spatrick           return false;
4943061da546Spatrick         }
4944dda28197Spatrick         if (!target.RemoveStopHookByID(user_id)) {
4945061da546Spatrick           result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n",
4946061da546Spatrick                                        command.GetArgumentAtIndex(i));
4947061da546Spatrick           return false;
4948061da546Spatrick         }
4949061da546Spatrick       }
4950061da546Spatrick     }
4951061da546Spatrick     result.SetStatus(eReturnStatusSuccessFinishNoResult);
4952061da546Spatrick     return result.Succeeded();
4953061da546Spatrick   }
4954061da546Spatrick };
4955061da546Spatrick 
4956061da546Spatrick #pragma mark CommandObjectTargetStopHookEnableDisable
4957061da546Spatrick 
4958061da546Spatrick // CommandObjectTargetStopHookEnableDisable
4959061da546Spatrick 
4960061da546Spatrick class CommandObjectTargetStopHookEnableDisable : public CommandObjectParsed {
4961061da546Spatrick public:
CommandObjectTargetStopHookEnableDisable(CommandInterpreter & interpreter,bool enable,const char * name,const char * help,const char * syntax)4962061da546Spatrick   CommandObjectTargetStopHookEnableDisable(CommandInterpreter &interpreter,
4963061da546Spatrick                                            bool enable, const char *name,
4964061da546Spatrick                                            const char *help, const char *syntax)
4965061da546Spatrick       : CommandObjectParsed(interpreter, name, help, syntax), m_enable(enable) {
4966*f6aab3d8Srobert     CommandArgumentData hook_arg{eArgTypeStopHookID, eArgRepeatStar};
4967*f6aab3d8Srobert     m_arguments.push_back({hook_arg});
4968061da546Spatrick   }
4969061da546Spatrick 
4970061da546Spatrick   ~CommandObjectTargetStopHookEnableDisable() override = default;
4971061da546Spatrick 
4972be691f3bSpatrick   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)4973be691f3bSpatrick   HandleArgumentCompletion(CompletionRequest &request,
4974be691f3bSpatrick                            OptionElementVector &opt_element_vector) override {
4975be691f3bSpatrick     if (request.GetCursorIndex())
4976be691f3bSpatrick       return;
4977be691f3bSpatrick     CommandCompletions::InvokeCommonCompletionCallbacks(
4978be691f3bSpatrick         GetCommandInterpreter(), CommandCompletions::eStopHookIDCompletion,
4979be691f3bSpatrick         request, nullptr);
4980be691f3bSpatrick   }
4981be691f3bSpatrick 
4982061da546Spatrick protected:
DoExecute(Args & command,CommandReturnObject & result)4983061da546Spatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
4984061da546Spatrick     Target &target = GetSelectedOrDummyTarget();
4985061da546Spatrick     // FIXME: see if we can use the breakpoint id style parser?
4986061da546Spatrick     size_t num_args = command.GetArgumentCount();
4987061da546Spatrick     bool success;
4988061da546Spatrick 
4989061da546Spatrick     if (num_args == 0) {
4990061da546Spatrick       target.SetAllStopHooksActiveState(m_enable);
4991061da546Spatrick     } else {
4992061da546Spatrick       for (size_t i = 0; i < num_args; i++) {
4993dda28197Spatrick         lldb::user_id_t user_id;
4994dda28197Spatrick         if (!llvm::to_integer(command.GetArgumentAtIndex(i), user_id)) {
4995061da546Spatrick           result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n",
4996061da546Spatrick                                        command.GetArgumentAtIndex(i));
4997061da546Spatrick           return false;
4998061da546Spatrick         }
4999061da546Spatrick         success = target.SetStopHookActiveStateByID(user_id, m_enable);
5000061da546Spatrick         if (!success) {
5001061da546Spatrick           result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n",
5002061da546Spatrick                                        command.GetArgumentAtIndex(i));
5003061da546Spatrick           return false;
5004061da546Spatrick         }
5005061da546Spatrick       }
5006061da546Spatrick     }
5007061da546Spatrick     result.SetStatus(eReturnStatusSuccessFinishNoResult);
5008061da546Spatrick     return result.Succeeded();
5009061da546Spatrick   }
5010061da546Spatrick 
5011061da546Spatrick private:
5012061da546Spatrick   bool m_enable;
5013061da546Spatrick };
5014061da546Spatrick 
5015061da546Spatrick #pragma mark CommandObjectTargetStopHookList
5016061da546Spatrick 
5017061da546Spatrick // CommandObjectTargetStopHookList
5018061da546Spatrick 
5019061da546Spatrick class CommandObjectTargetStopHookList : public CommandObjectParsed {
5020061da546Spatrick public:
CommandObjectTargetStopHookList(CommandInterpreter & interpreter)5021061da546Spatrick   CommandObjectTargetStopHookList(CommandInterpreter &interpreter)
5022061da546Spatrick       : CommandObjectParsed(interpreter, "target stop-hook list",
5023*f6aab3d8Srobert                             "List all stop-hooks.", "target stop-hook list") {}
5024061da546Spatrick 
5025061da546Spatrick   ~CommandObjectTargetStopHookList() override = default;
5026061da546Spatrick 
5027061da546Spatrick protected:
DoExecute(Args & command,CommandReturnObject & result)5028061da546Spatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
5029061da546Spatrick     Target &target = GetSelectedOrDummyTarget();
5030061da546Spatrick 
5031061da546Spatrick     size_t num_hooks = target.GetNumStopHooks();
5032061da546Spatrick     if (num_hooks == 0) {
5033061da546Spatrick       result.GetOutputStream().PutCString("No stop hooks.\n");
5034061da546Spatrick     } else {
5035061da546Spatrick       for (size_t i = 0; i < num_hooks; i++) {
5036061da546Spatrick         Target::StopHookSP this_hook = target.GetStopHookAtIndex(i);
5037061da546Spatrick         if (i > 0)
5038061da546Spatrick           result.GetOutputStream().PutCString("\n");
5039061da546Spatrick         this_hook->GetDescription(&(result.GetOutputStream()),
5040061da546Spatrick                                   eDescriptionLevelFull);
5041061da546Spatrick       }
5042061da546Spatrick     }
5043061da546Spatrick     result.SetStatus(eReturnStatusSuccessFinishResult);
5044061da546Spatrick     return result.Succeeded();
5045061da546Spatrick   }
5046061da546Spatrick };
5047061da546Spatrick 
5048061da546Spatrick #pragma mark CommandObjectMultiwordTargetStopHooks
5049061da546Spatrick 
5050061da546Spatrick // CommandObjectMultiwordTargetStopHooks
5051061da546Spatrick 
5052061da546Spatrick class CommandObjectMultiwordTargetStopHooks : public CommandObjectMultiword {
5053061da546Spatrick public:
CommandObjectMultiwordTargetStopHooks(CommandInterpreter & interpreter)5054061da546Spatrick   CommandObjectMultiwordTargetStopHooks(CommandInterpreter &interpreter)
5055061da546Spatrick       : CommandObjectMultiword(
5056061da546Spatrick             interpreter, "target stop-hook",
5057061da546Spatrick             "Commands for operating on debugger target stop-hooks.",
5058061da546Spatrick             "target stop-hook <subcommand> [<subcommand-options>]") {
5059061da546Spatrick     LoadSubCommand("add", CommandObjectSP(
5060061da546Spatrick                               new CommandObjectTargetStopHookAdd(interpreter)));
5061061da546Spatrick     LoadSubCommand(
5062061da546Spatrick         "delete",
5063061da546Spatrick         CommandObjectSP(new CommandObjectTargetStopHookDelete(interpreter)));
5064061da546Spatrick     LoadSubCommand("disable",
5065061da546Spatrick                    CommandObjectSP(new CommandObjectTargetStopHookEnableDisable(
5066061da546Spatrick                        interpreter, false, "target stop-hook disable [<id>]",
5067061da546Spatrick                        "Disable a stop-hook.", "target stop-hook disable")));
5068061da546Spatrick     LoadSubCommand("enable",
5069061da546Spatrick                    CommandObjectSP(new CommandObjectTargetStopHookEnableDisable(
5070061da546Spatrick                        interpreter, true, "target stop-hook enable [<id>]",
5071061da546Spatrick                        "Enable a stop-hook.", "target stop-hook enable")));
5072061da546Spatrick     LoadSubCommand("list", CommandObjectSP(new CommandObjectTargetStopHookList(
5073061da546Spatrick                                interpreter)));
5074061da546Spatrick   }
5075061da546Spatrick 
5076061da546Spatrick   ~CommandObjectMultiwordTargetStopHooks() override = default;
5077061da546Spatrick };
5078061da546Spatrick 
5079*f6aab3d8Srobert #pragma mark CommandObjectTargetDumpTypesystem
5080*f6aab3d8Srobert 
5081*f6aab3d8Srobert /// Dumps the TypeSystem of the selected Target.
5082*f6aab3d8Srobert class CommandObjectTargetDumpTypesystem : public CommandObjectParsed {
5083*f6aab3d8Srobert public:
CommandObjectTargetDumpTypesystem(CommandInterpreter & interpreter)5084*f6aab3d8Srobert   CommandObjectTargetDumpTypesystem(CommandInterpreter &interpreter)
5085*f6aab3d8Srobert       : CommandObjectParsed(
5086*f6aab3d8Srobert             interpreter, "target dump typesystem",
5087*f6aab3d8Srobert             "Dump the state of the target's internal type system.\n"
5088*f6aab3d8Srobert             "Intended to be used for debugging LLDB itself.",
5089*f6aab3d8Srobert             nullptr, eCommandRequiresTarget) {}
5090*f6aab3d8Srobert 
5091*f6aab3d8Srobert   ~CommandObjectTargetDumpTypesystem() override = default;
5092*f6aab3d8Srobert 
5093*f6aab3d8Srobert protected:
DoExecute(Args & command,CommandReturnObject & result)5094*f6aab3d8Srobert   bool DoExecute(Args &command, CommandReturnObject &result) override {
5095*f6aab3d8Srobert     // Go over every scratch TypeSystem and dump to the command output.
5096*f6aab3d8Srobert     for (lldb::TypeSystemSP ts : GetSelectedTarget().GetScratchTypeSystems())
5097*f6aab3d8Srobert       if (ts)
5098*f6aab3d8Srobert         ts->Dump(result.GetOutputStream().AsRawOstream());
5099*f6aab3d8Srobert 
5100*f6aab3d8Srobert     result.SetStatus(eReturnStatusSuccessFinishResult);
5101*f6aab3d8Srobert     return result.Succeeded();
5102*f6aab3d8Srobert   }
5103*f6aab3d8Srobert };
5104*f6aab3d8Srobert 
5105*f6aab3d8Srobert #pragma mark CommandObjectTargetDump
5106*f6aab3d8Srobert 
5107*f6aab3d8Srobert /// Multi-word command for 'target dump'.
5108*f6aab3d8Srobert class CommandObjectTargetDump : public CommandObjectMultiword {
5109*f6aab3d8Srobert public:
5110*f6aab3d8Srobert   // Constructors and Destructors
CommandObjectTargetDump(CommandInterpreter & interpreter)5111*f6aab3d8Srobert   CommandObjectTargetDump(CommandInterpreter &interpreter)
5112*f6aab3d8Srobert       : CommandObjectMultiword(
5113*f6aab3d8Srobert             interpreter, "target dump",
5114*f6aab3d8Srobert             "Commands for dumping information about the target.",
5115*f6aab3d8Srobert             "target dump [typesystem]") {
5116*f6aab3d8Srobert     LoadSubCommand(
5117*f6aab3d8Srobert         "typesystem",
5118*f6aab3d8Srobert         CommandObjectSP(new CommandObjectTargetDumpTypesystem(interpreter)));
5119*f6aab3d8Srobert   }
5120*f6aab3d8Srobert 
5121*f6aab3d8Srobert   ~CommandObjectTargetDump() override = default;
5122*f6aab3d8Srobert };
5123*f6aab3d8Srobert 
5124061da546Spatrick #pragma mark CommandObjectMultiwordTarget
5125061da546Spatrick 
5126061da546Spatrick // CommandObjectMultiwordTarget
5127061da546Spatrick 
CommandObjectMultiwordTarget(CommandInterpreter & interpreter)5128061da546Spatrick CommandObjectMultiwordTarget::CommandObjectMultiwordTarget(
5129061da546Spatrick     CommandInterpreter &interpreter)
5130061da546Spatrick     : CommandObjectMultiword(interpreter, "target",
5131061da546Spatrick                              "Commands for operating on debugger targets.",
5132061da546Spatrick                              "target <subcommand> [<subcommand-options>]") {
5133061da546Spatrick   LoadSubCommand("create",
5134061da546Spatrick                  CommandObjectSP(new CommandObjectTargetCreate(interpreter)));
5135061da546Spatrick   LoadSubCommand("delete",
5136061da546Spatrick                  CommandObjectSP(new CommandObjectTargetDelete(interpreter)));
5137*f6aab3d8Srobert   LoadSubCommand("dump",
5138*f6aab3d8Srobert                  CommandObjectSP(new CommandObjectTargetDump(interpreter)));
5139061da546Spatrick   LoadSubCommand("list",
5140061da546Spatrick                  CommandObjectSP(new CommandObjectTargetList(interpreter)));
5141061da546Spatrick   LoadSubCommand("select",
5142061da546Spatrick                  CommandObjectSP(new CommandObjectTargetSelect(interpreter)));
5143dda28197Spatrick   LoadSubCommand("show-launch-environment",
5144dda28197Spatrick                  CommandObjectSP(new CommandObjectTargetShowLaunchEnvironment(
5145dda28197Spatrick                      interpreter)));
5146061da546Spatrick   LoadSubCommand(
5147061da546Spatrick       "stop-hook",
5148061da546Spatrick       CommandObjectSP(new CommandObjectMultiwordTargetStopHooks(interpreter)));
5149061da546Spatrick   LoadSubCommand("modules",
5150061da546Spatrick                  CommandObjectSP(new CommandObjectTargetModules(interpreter)));
5151061da546Spatrick   LoadSubCommand("symbols",
5152061da546Spatrick                  CommandObjectSP(new CommandObjectTargetSymbols(interpreter)));
5153061da546Spatrick   LoadSubCommand("variable",
5154061da546Spatrick                  CommandObjectSP(new CommandObjectTargetVariable(interpreter)));
5155061da546Spatrick }
5156061da546Spatrick 
5157061da546Spatrick CommandObjectMultiwordTarget::~CommandObjectMultiwordTarget() = default;
5158