1ac7ddfbfSEd Maste //===-- CommandObjectTarget.cpp ---------------------------------*- C++ -*-===//
2ac7ddfbfSEd Maste //
3ac7ddfbfSEd Maste //                     The LLVM Compiler Infrastructure
4ac7ddfbfSEd Maste //
5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source
6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details.
7ac7ddfbfSEd Maste //
8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===//
9ac7ddfbfSEd Maste 
10ac7ddfbfSEd Maste #include "CommandObjectTarget.h"
11ac7ddfbfSEd Maste 
12ac7ddfbfSEd Maste #include "lldb/Core/Debugger.h"
1312b93ac6SEd Maste #include "lldb/Core/IOHandler.h"
14ac7ddfbfSEd Maste #include "lldb/Core/Module.h"
15ac7ddfbfSEd Maste #include "lldb/Core/ModuleSpec.h"
16ac7ddfbfSEd Maste #include "lldb/Core/Section.h"
17ac7ddfbfSEd Maste #include "lldb/Core/ValueObjectVariable.h"
1835617911SEd Maste #include "lldb/DataFormatters/ValueObjectPrinter.h"
19f678e45dSDimitry Andric #include "lldb/Host/OptionParser.h"
201c3bbb01SEd Maste #include "lldb/Host/StringConvert.h"
21ac7ddfbfSEd Maste #include "lldb/Host/Symbols.h"
22ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandInterpreter.h"
23ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandReturnObject.h"
244ba319b5SDimitry Andric #include "lldb/Interpreter/OptionArgParser.h"
25ac7ddfbfSEd Maste #include "lldb/Interpreter/OptionGroupArchitecture.h"
26ac7ddfbfSEd Maste #include "lldb/Interpreter/OptionGroupBoolean.h"
27ac7ddfbfSEd Maste #include "lldb/Interpreter/OptionGroupFile.h"
28ac7ddfbfSEd Maste #include "lldb/Interpreter/OptionGroupFormat.h"
29ac7ddfbfSEd Maste #include "lldb/Interpreter/OptionGroupPlatform.h"
30435933ddSDimitry Andric #include "lldb/Interpreter/OptionGroupString.h"
31ac7ddfbfSEd Maste #include "lldb/Interpreter/OptionGroupUInt64.h"
32ac7ddfbfSEd Maste #include "lldb/Interpreter/OptionGroupUUID.h"
33ac7ddfbfSEd Maste #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
34435933ddSDimitry Andric #include "lldb/Interpreter/OptionGroupVariable.h"
35435933ddSDimitry Andric #include "lldb/Interpreter/Options.h"
36ac7ddfbfSEd Maste #include "lldb/Symbol/CompileUnit.h"
37ac7ddfbfSEd Maste #include "lldb/Symbol/FuncUnwinders.h"
38ac7ddfbfSEd Maste #include "lldb/Symbol/LineTable.h"
39ac7ddfbfSEd Maste #include "lldb/Symbol/ObjectFile.h"
40ac7ddfbfSEd Maste #include "lldb/Symbol/SymbolFile.h"
41ac7ddfbfSEd Maste #include "lldb/Symbol/SymbolVendor.h"
42ac7ddfbfSEd Maste #include "lldb/Symbol/UnwindPlan.h"
43ac7ddfbfSEd Maste #include "lldb/Symbol/VariableList.h"
441c3bbb01SEd Maste #include "lldb/Target/ABI.h"
45ac7ddfbfSEd Maste #include "lldb/Target/Process.h"
464ba319b5SDimitry Andric #include "lldb/Target/RegisterContext.h"
4712b93ac6SEd Maste #include "lldb/Target/SectionLoadList.h"
48ac7ddfbfSEd Maste #include "lldb/Target/StackFrame.h"
49ac7ddfbfSEd Maste #include "lldb/Target/Thread.h"
50ac7ddfbfSEd Maste #include "lldb/Target/ThreadSpec.h"
514ba319b5SDimitry Andric #include "lldb/Utility/Args.h"
52*b5893f02SDimitry Andric #include "lldb/Utility/State.h"
53a580b014SDimitry Andric #include "lldb/Utility/Timer.h"
54ac7ddfbfSEd Maste 
55f678e45dSDimitry Andric #include "llvm/Support/FileSystem.h"
56acac075bSDimitry Andric #include "llvm/Support/FormatAdapters.h"
57f678e45dSDimitry Andric 
58435933ddSDimitry Andric #include <cerrno>
59435933ddSDimitry Andric 
60ac7ddfbfSEd Maste using namespace lldb;
61ac7ddfbfSEd Maste using namespace lldb_private;
62ac7ddfbfSEd Maste 
DumpTargetInfo(uint32_t target_idx,Target * target,const char * prefix_cstr,bool show_stopped_process_status,Stream & strm)63435933ddSDimitry Andric static void DumpTargetInfo(uint32_t target_idx, Target *target,
64435933ddSDimitry Andric                            const char *prefix_cstr,
65435933ddSDimitry Andric                            bool show_stopped_process_status, Stream &strm) {
66ac7ddfbfSEd Maste   const ArchSpec &target_arch = target->GetArchitecture();
67ac7ddfbfSEd Maste 
68ac7ddfbfSEd Maste   Module *exe_module = target->GetExecutableModulePointer();
69ac7ddfbfSEd Maste   char exe_path[PATH_MAX];
70ac7ddfbfSEd Maste   bool exe_valid = false;
71ac7ddfbfSEd Maste   if (exe_module)
72ac7ddfbfSEd Maste     exe_valid = exe_module->GetFileSpec().GetPath(exe_path, sizeof(exe_path));
73ac7ddfbfSEd Maste 
74ac7ddfbfSEd Maste   if (!exe_valid)
75ac7ddfbfSEd Maste     ::strcpy(exe_path, "<none>");
76ac7ddfbfSEd Maste 
77435933ddSDimitry Andric   strm.Printf("%starget #%u: %s", prefix_cstr ? prefix_cstr : "", target_idx,
78435933ddSDimitry Andric               exe_path);
79ac7ddfbfSEd Maste 
80ac7ddfbfSEd Maste   uint32_t properties = 0;
81435933ddSDimitry Andric   if (target_arch.IsValid()) {
829f2f44ceSEd Maste     strm.Printf("%sarch=", properties++ > 0 ? ", " : " ( ");
839f2f44ceSEd Maste     target_arch.DumpTriple(strm);
84ac7ddfbfSEd Maste     properties++;
85ac7ddfbfSEd Maste   }
86ac7ddfbfSEd Maste   PlatformSP platform_sp(target->GetPlatform());
87ac7ddfbfSEd Maste   if (platform_sp)
88435933ddSDimitry Andric     strm.Printf("%splatform=%s", properties++ > 0 ? ", " : " ( ",
89435933ddSDimitry Andric                 platform_sp->GetName().GetCString());
90ac7ddfbfSEd Maste 
91ac7ddfbfSEd Maste   ProcessSP process_sp(target->GetProcessSP());
92ac7ddfbfSEd Maste   bool show_process_status = false;
93435933ddSDimitry Andric   if (process_sp) {
94ac7ddfbfSEd Maste     lldb::pid_t pid = process_sp->GetID();
95ac7ddfbfSEd Maste     StateType state = process_sp->GetState();
96ac7ddfbfSEd Maste     if (show_stopped_process_status)
97ac7ddfbfSEd Maste       show_process_status = StateIsStoppedState(state, true);
98ac7ddfbfSEd Maste     const char *state_cstr = StateAsCString(state);
99ac7ddfbfSEd Maste     if (pid != LLDB_INVALID_PROCESS_ID)
100ac7ddfbfSEd Maste       strm.Printf("%spid=%" PRIu64, properties++ > 0 ? ", " : " ( ", pid);
101ac7ddfbfSEd Maste     strm.Printf("%sstate=%s", properties++ > 0 ? ", " : " ( ", state_cstr);
102ac7ddfbfSEd Maste   }
103ac7ddfbfSEd Maste   if (properties > 0)
104ac7ddfbfSEd Maste     strm.PutCString(" )\n");
105ac7ddfbfSEd Maste   else
106ac7ddfbfSEd Maste     strm.EOL();
107435933ddSDimitry Andric   if (show_process_status) {
108ac7ddfbfSEd Maste     const bool only_threads_with_stop_reason = true;
109ac7ddfbfSEd Maste     const uint32_t start_frame = 0;
110ac7ddfbfSEd Maste     const uint32_t num_frames = 1;
111ac7ddfbfSEd Maste     const uint32_t num_frames_with_source = 1;
112435933ddSDimitry Andric     const bool     stop_format = false;
113ac7ddfbfSEd Maste     process_sp->GetStatus(strm);
114435933ddSDimitry Andric     process_sp->GetThreadStatus(strm, only_threads_with_stop_reason,
115435933ddSDimitry Andric                                 start_frame, num_frames,
116435933ddSDimitry Andric                                 num_frames_with_source, stop_format);
117ac7ddfbfSEd Maste   }
118ac7ddfbfSEd Maste }
119ac7ddfbfSEd Maste 
DumpTargetList(TargetList & target_list,bool show_stopped_process_status,Stream & strm)120435933ddSDimitry Andric static uint32_t DumpTargetList(TargetList &target_list,
121435933ddSDimitry Andric                                bool show_stopped_process_status, Stream &strm) {
122ac7ddfbfSEd Maste   const uint32_t num_targets = target_list.GetNumTargets();
123435933ddSDimitry Andric   if (num_targets) {
124ac7ddfbfSEd Maste     TargetSP selected_target_sp(target_list.GetSelectedTarget());
125ac7ddfbfSEd Maste     strm.PutCString("Current targets:\n");
126435933ddSDimitry Andric     for (uint32_t i = 0; i < num_targets; ++i) {
127ac7ddfbfSEd Maste       TargetSP target_sp(target_list.GetTargetAtIndex(i));
128435933ddSDimitry Andric       if (target_sp) {
129ac7ddfbfSEd Maste         bool is_selected = target_sp.get() == selected_target_sp.get();
130435933ddSDimitry Andric         DumpTargetInfo(i, target_sp.get(), is_selected ? "* " : "  ",
131435933ddSDimitry Andric                        show_stopped_process_status, strm);
132ac7ddfbfSEd Maste       }
133ac7ddfbfSEd Maste     }
134ac7ddfbfSEd Maste   }
135ac7ddfbfSEd Maste   return num_targets;
136ac7ddfbfSEd Maste }
1374bb0738eSEd Maste 
138*b5893f02SDimitry Andric // Note that the negation in the argument name causes a slightly confusing
139*b5893f02SDimitry Andric // mapping of the enum values,
140*b5893f02SDimitry Andric static constexpr OptionEnumValueElement g_dependents_enumaration[] = {
141*b5893f02SDimitry Andric     {eLoadDependentsDefault, "default",
142*b5893f02SDimitry Andric      "Only load dependents when the target is an executable."},
143*b5893f02SDimitry Andric     {eLoadDependentsNo, "true",
144*b5893f02SDimitry Andric      "Don't load dependents, even if the target is an executable."},
145*b5893f02SDimitry Andric     {eLoadDependentsYes, "false",
146*b5893f02SDimitry Andric      "Load dependents, even if the target is not an executable."}};
147*b5893f02SDimitry Andric 
148*b5893f02SDimitry Andric static constexpr OptionDefinition g_dependents_options[] = {
149*b5893f02SDimitry Andric     {LLDB_OPT_SET_1, false, "no-dependents", 'd',
150*b5893f02SDimitry Andric      OptionParser::eOptionalArgument, nullptr,
151*b5893f02SDimitry Andric      OptionEnumValues(g_dependents_enumaration), 0, eArgTypeValue,
152*b5893f02SDimitry Andric      "Whether or not to load dependents when creating a target. If the option "
153*b5893f02SDimitry Andric      "is not specified, the value is implicitly 'default'. If the option is "
154*b5893f02SDimitry Andric      "specified but without a value, the value is implicitly 'true'."}};
155*b5893f02SDimitry Andric 
156*b5893f02SDimitry Andric class OptionGroupDependents : public OptionGroup {
157*b5893f02SDimitry Andric public:
OptionGroupDependents()158*b5893f02SDimitry Andric   OptionGroupDependents() {}
159*b5893f02SDimitry Andric 
~OptionGroupDependents()160*b5893f02SDimitry Andric   ~OptionGroupDependents() override {}
161*b5893f02SDimitry Andric 
GetDefinitions()162*b5893f02SDimitry Andric   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
163*b5893f02SDimitry Andric     return llvm::makeArrayRef(g_dependents_options);
164*b5893f02SDimitry Andric   }
165*b5893f02SDimitry Andric 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_value,ExecutionContext * execution_context)166*b5893f02SDimitry Andric   Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
167*b5893f02SDimitry Andric                         ExecutionContext *execution_context) override {
168*b5893f02SDimitry Andric     Status error;
169*b5893f02SDimitry Andric 
170*b5893f02SDimitry Andric     // For compatibility no value means don't load dependents.
171*b5893f02SDimitry Andric     if (option_value.empty()) {
172*b5893f02SDimitry Andric       m_load_dependent_files = eLoadDependentsNo;
173*b5893f02SDimitry Andric       return error;
174*b5893f02SDimitry Andric     }
175*b5893f02SDimitry Andric 
176*b5893f02SDimitry Andric     const char short_option = g_dependents_options[option_idx].short_option;
177*b5893f02SDimitry Andric     if (short_option == 'd') {
178*b5893f02SDimitry Andric       LoadDependentFiles tmp_load_dependents;
179*b5893f02SDimitry Andric       tmp_load_dependents = (LoadDependentFiles)OptionArgParser::ToOptionEnum(
180*b5893f02SDimitry Andric           option_value, g_dependents_options[option_idx].enum_values, 0, error);
181*b5893f02SDimitry Andric       if (error.Success())
182*b5893f02SDimitry Andric         m_load_dependent_files = tmp_load_dependents;
183*b5893f02SDimitry Andric     } else {
184*b5893f02SDimitry Andric       error.SetErrorStringWithFormat("unrecognized short option '%c'",
185*b5893f02SDimitry Andric                                      short_option);
186*b5893f02SDimitry Andric     }
187*b5893f02SDimitry Andric 
188*b5893f02SDimitry Andric     return error;
189*b5893f02SDimitry Andric   }
190*b5893f02SDimitry Andric 
191*b5893f02SDimitry Andric   Status SetOptionValue(uint32_t, const char *, ExecutionContext *) = delete;
192*b5893f02SDimitry Andric 
OptionParsingStarting(ExecutionContext * execution_context)193*b5893f02SDimitry Andric   void OptionParsingStarting(ExecutionContext *execution_context) override {
194*b5893f02SDimitry Andric     m_load_dependent_files = eLoadDependentsDefault;
195*b5893f02SDimitry Andric   }
196*b5893f02SDimitry Andric 
197*b5893f02SDimitry Andric   LoadDependentFiles m_load_dependent_files;
198*b5893f02SDimitry Andric 
199*b5893f02SDimitry Andric private:
200*b5893f02SDimitry Andric   DISALLOW_COPY_AND_ASSIGN(OptionGroupDependents);
201*b5893f02SDimitry Andric };
202*b5893f02SDimitry Andric 
203ac7ddfbfSEd Maste #pragma mark CommandObjectTargetCreate
204ac7ddfbfSEd Maste 
205ac7ddfbfSEd Maste //-------------------------------------------------------------------------
206ac7ddfbfSEd Maste // "target create"
207ac7ddfbfSEd Maste //-------------------------------------------------------------------------
208ac7ddfbfSEd Maste 
209435933ddSDimitry Andric class CommandObjectTargetCreate : public CommandObjectParsed {
210ac7ddfbfSEd Maste public:
CommandObjectTargetCreate(CommandInterpreter & interpreter)211435933ddSDimitry Andric   CommandObjectTargetCreate(CommandInterpreter &interpreter)
212435933ddSDimitry Andric       : CommandObjectParsed(
213435933ddSDimitry Andric             interpreter, "target create",
214ac7ddfbfSEd Maste             "Create a target using the argument as the main executable.",
2154bb0738eSEd Maste             nullptr),
216435933ddSDimitry Andric         m_option_group(), m_arch_option(),
217435933ddSDimitry Andric         m_core_file(LLDB_OPT_SET_1, false, "core", 'c', 0, eArgTypeFilename,
218435933ddSDimitry Andric                     "Fullpath to a core file to use for this target."),
219435933ddSDimitry Andric         m_platform_path(LLDB_OPT_SET_1, false, "platform-path", 'P', 0,
220435933ddSDimitry Andric                         eArgTypePath,
221435933ddSDimitry Andric                         "Path to the remote file to use for this target."),
222435933ddSDimitry Andric         m_symbol_file(LLDB_OPT_SET_1, false, "symfile", 's', 0,
223*b5893f02SDimitry Andric                       eArgTypeFilename,
224*b5893f02SDimitry Andric                       "Fullpath to a stand alone debug "
225435933ddSDimitry Andric                       "symbols file for when debug symbols "
226435933ddSDimitry Andric                       "are not in the executable."),
227435933ddSDimitry Andric         m_remote_file(
228435933ddSDimitry Andric             LLDB_OPT_SET_1, false, "remote-file", 'r', 0, eArgTypeFilename,
229435933ddSDimitry Andric             "Fullpath to the file on the remote host if debugging remotely."),
230*b5893f02SDimitry Andric         m_add_dependents() {
231ac7ddfbfSEd Maste     CommandArgumentEntry arg;
232ac7ddfbfSEd Maste     CommandArgumentData file_arg;
233ac7ddfbfSEd Maste 
234ac7ddfbfSEd Maste     // Define the first (and only) variant of this arg.
235ac7ddfbfSEd Maste     file_arg.arg_type = eArgTypeFilename;
236ac7ddfbfSEd Maste     file_arg.arg_repetition = eArgRepeatPlain;
237ac7ddfbfSEd Maste 
238435933ddSDimitry Andric     // There is only one variant this argument could be; put it into the
239435933ddSDimitry Andric     // argument entry.
240ac7ddfbfSEd Maste     arg.push_back(file_arg);
241ac7ddfbfSEd Maste 
242ac7ddfbfSEd Maste     // Push the data for the first argument into the m_arguments vector.
243ac7ddfbfSEd Maste     m_arguments.push_back(arg);
244ac7ddfbfSEd Maste 
245ac7ddfbfSEd Maste     m_option_group.Append(&m_arch_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
246ac7ddfbfSEd Maste     m_option_group.Append(&m_core_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
24735617911SEd Maste     m_option_group.Append(&m_platform_path, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
248ac7ddfbfSEd Maste     m_option_group.Append(&m_symbol_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
249ac7ddfbfSEd Maste     m_option_group.Append(&m_remote_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
250ac7ddfbfSEd Maste     m_option_group.Append(&m_add_dependents, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
251ac7ddfbfSEd Maste     m_option_group.Finalize();
252ac7ddfbfSEd Maste   }
253ac7ddfbfSEd Maste 
2544bb0738eSEd Maste   ~CommandObjectTargetCreate() override = default;
255ac7ddfbfSEd Maste 
GetOptions()256435933ddSDimitry Andric   Options *GetOptions() override { return &m_option_group; }
257ac7ddfbfSEd Maste 
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)2584ba319b5SDimitry Andric   int HandleArgumentCompletion(
2594ba319b5SDimitry Andric       CompletionRequest &request,
2604ba319b5SDimitry Andric       OptionElementVector &opt_element_vector) override {
261435933ddSDimitry Andric     CommandCompletions::InvokeCommonCompletionCallbacks(
262435933ddSDimitry Andric         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
2634ba319b5SDimitry Andric         request, nullptr);
2644ba319b5SDimitry Andric     return request.GetNumberOfMatches();
265ac7ddfbfSEd Maste   }
266ac7ddfbfSEd Maste 
267ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)268435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
269ac7ddfbfSEd Maste     const size_t argc = command.GetArgumentCount();
270ac7ddfbfSEd Maste     FileSpec core_file(m_core_file.GetOptionValue().GetCurrentValue());
271ac7ddfbfSEd Maste     FileSpec remote_file(m_remote_file.GetOptionValue().GetCurrentValue());
272ac7ddfbfSEd Maste 
273435933ddSDimitry Andric     if (core_file) {
274*b5893f02SDimitry Andric       if (!FileSystem::Instance().Exists(core_file)) {
275435933ddSDimitry Andric         result.AppendErrorWithFormat("core file '%s' doesn't exist",
276435933ddSDimitry Andric                                      core_file.GetPath().c_str());
2770127ef0fSEd Maste         result.SetStatus(eReturnStatusFailed);
2780127ef0fSEd Maste         return false;
2790127ef0fSEd Maste       }
280*b5893f02SDimitry Andric       if (!FileSystem::Instance().Readable(core_file)) {
281435933ddSDimitry Andric         result.AppendErrorWithFormat("core file '%s' is not readable",
282435933ddSDimitry Andric                                      core_file.GetPath().c_str());
2830127ef0fSEd Maste         result.SetStatus(eReturnStatusFailed);
2840127ef0fSEd Maste         return false;
2850127ef0fSEd Maste       }
2860127ef0fSEd Maste     }
2870127ef0fSEd Maste 
288435933ddSDimitry Andric     if (argc == 1 || core_file || remote_file) {
289ac7ddfbfSEd Maste       FileSpec symfile(m_symbol_file.GetOptionValue().GetCurrentValue());
290435933ddSDimitry Andric       if (symfile) {
291*b5893f02SDimitry Andric         if (FileSystem::Instance().Exists(symfile)) {
292*b5893f02SDimitry Andric           if (!FileSystem::Instance().Readable(symfile)) {
293435933ddSDimitry Andric             result.AppendErrorWithFormat("symbol file '%s' is not readable",
294435933ddSDimitry Andric                                          symfile.GetPath().c_str());
2950127ef0fSEd Maste             result.SetStatus(eReturnStatusFailed);
2960127ef0fSEd Maste             return false;
2970127ef0fSEd Maste           }
298435933ddSDimitry Andric         } else {
299ac7ddfbfSEd Maste           char symfile_path[PATH_MAX];
300ac7ddfbfSEd Maste           symfile.GetPath(symfile_path, sizeof(symfile_path));
301435933ddSDimitry Andric           result.AppendErrorWithFormat("invalid symbol file path '%s'",
302435933ddSDimitry Andric                                        symfile_path);
303ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusFailed);
304ac7ddfbfSEd Maste           return false;
305ac7ddfbfSEd Maste         }
306ac7ddfbfSEd Maste       }
307ac7ddfbfSEd Maste 
308ac7ddfbfSEd Maste       const char *file_path = command.GetArgumentAtIndex(0);
3095517e702SDimitry Andric       static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
3105517e702SDimitry Andric       Timer scoped_timer(func_cat, "(lldb) target create '%s'", file_path);
31135617911SEd Maste       FileSpec file_spec;
31235617911SEd Maste 
313*b5893f02SDimitry Andric       if (file_path) {
314*b5893f02SDimitry Andric         file_spec.SetFile(file_path, FileSpec::Style::native);
315*b5893f02SDimitry Andric         FileSystem::Instance().Resolve(file_spec);
316*b5893f02SDimitry Andric       }
31735617911SEd Maste 
31835617911SEd Maste       bool must_set_platform_path = false;
31935617911SEd Maste 
320ac7ddfbfSEd Maste       Debugger &debugger = m_interpreter.GetDebugger();
3211c3bbb01SEd Maste 
3221c3bbb01SEd Maste       TargetSP target_sp;
323435933ddSDimitry Andric       llvm::StringRef arch_cstr = m_arch_option.GetArchitectureName();
3245517e702SDimitry Andric       Status error(debugger.GetTargetList().CreateTarget(
325*b5893f02SDimitry Andric           debugger, file_path, arch_cstr,
326*b5893f02SDimitry Andric           m_add_dependents.m_load_dependent_files, nullptr, target_sp));
3271c3bbb01SEd Maste 
328435933ddSDimitry Andric       if (target_sp) {
329435933ddSDimitry Andric         // Only get the platform after we create the target because we might
3304ba319b5SDimitry Andric         // have switched platforms depending on what the arguments were to
3314ba319b5SDimitry Andric         // CreateTarget() we can't rely on the selected platform.
3321c3bbb01SEd Maste 
3331c3bbb01SEd Maste         PlatformSP platform_sp = target_sp->GetPlatform();
33435617911SEd Maste 
335435933ddSDimitry Andric         if (remote_file) {
336435933ddSDimitry Andric           if (platform_sp) {
33735617911SEd Maste             // I have a remote file.. two possible cases
338*b5893f02SDimitry Andric             if (file_spec && FileSystem::Instance().Exists(file_spec)) {
33935617911SEd Maste               // if the remote file does not exist, push it there
340435933ddSDimitry Andric               if (!platform_sp->GetFileExists(remote_file)) {
3415517e702SDimitry Andric                 Status err = platform_sp->PutFile(file_spec, remote_file);
342435933ddSDimitry Andric                 if (err.Fail()) {
34335617911SEd Maste                   result.AppendError(err.AsCString());
34435617911SEd Maste                   result.SetStatus(eReturnStatusFailed);
34535617911SEd Maste                   return false;
34635617911SEd Maste                 }
34735617911SEd Maste               }
348435933ddSDimitry Andric             } else {
34935617911SEd Maste               // there is no local file and we need one
350435933ddSDimitry Andric               // in order to make the remote ---> local transfer we need a
351435933ddSDimitry Andric               // platform
352435933ddSDimitry Andric               // TODO: if the user has passed in a --platform argument, use it
353435933ddSDimitry Andric               // to fetch the right platform
354435933ddSDimitry Andric               if (!platform_sp) {
355435933ddSDimitry Andric                 result.AppendError(
356435933ddSDimitry Andric                     "unable to perform remote debugging without a platform");
35735617911SEd Maste                 result.SetStatus(eReturnStatusFailed);
35835617911SEd Maste                 return false;
35935617911SEd Maste               }
360435933ddSDimitry Andric               if (file_path) {
36135617911SEd Maste                 // copy the remote file to the local file
3625517e702SDimitry Andric                 Status err = platform_sp->GetFile(remote_file, file_spec);
363435933ddSDimitry Andric                 if (err.Fail()) {
36435617911SEd Maste                   result.AppendError(err.AsCString());
36535617911SEd Maste                   result.SetStatus(eReturnStatusFailed);
36635617911SEd Maste                   return false;
36735617911SEd Maste                 }
368435933ddSDimitry Andric               } else {
36935617911SEd Maste                 // make up a local file
370435933ddSDimitry Andric                 result.AppendError("remote --> local transfer without local "
371435933ddSDimitry Andric                                    "path is not implemented yet");
37235617911SEd Maste                 result.SetStatus(eReturnStatusFailed);
37335617911SEd Maste                 return false;
37435617911SEd Maste               }
37535617911SEd Maste             }
376435933ddSDimitry Andric           } else {
3771c3bbb01SEd Maste             result.AppendError("no platform found for target");
3781c3bbb01SEd Maste             result.SetStatus(eReturnStatusFailed);
3791c3bbb01SEd Maste             return false;
3801c3bbb01SEd Maste           }
3811c3bbb01SEd Maste         }
3821c3bbb01SEd Maste 
383435933ddSDimitry Andric         if (symfile || remote_file) {
384ac7ddfbfSEd Maste           ModuleSP module_sp(target_sp->GetExecutableModule());
385435933ddSDimitry Andric           if (module_sp) {
386ac7ddfbfSEd Maste             if (symfile)
387ac7ddfbfSEd Maste               module_sp->SetSymbolFileFileSpec(symfile);
388435933ddSDimitry Andric             if (remote_file) {
389ac7ddfbfSEd Maste               std::string remote_path = remote_file.GetPath();
390ac7ddfbfSEd Maste               target_sp->SetArg0(remote_path.c_str());
391ac7ddfbfSEd Maste               module_sp->SetPlatformFileSpec(remote_file);
392ac7ddfbfSEd Maste             }
393ac7ddfbfSEd Maste           }
394ac7ddfbfSEd Maste         }
395ac7ddfbfSEd Maste 
396ac7ddfbfSEd Maste         debugger.GetTargetList().SetSelectedTarget(target_sp.get());
397435933ddSDimitry Andric         if (must_set_platform_path) {
39835617911SEd Maste           ModuleSpec main_module_spec(file_spec);
39935617911SEd Maste           ModuleSP module_sp = target_sp->GetSharedModule(main_module_spec);
40035617911SEd Maste           if (module_sp)
40135617911SEd Maste             module_sp->SetPlatformFileSpec(remote_file);
40235617911SEd Maste         }
403435933ddSDimitry Andric         if (core_file) {
404ac7ddfbfSEd Maste           char core_path[PATH_MAX];
405ac7ddfbfSEd Maste           core_file.GetPath(core_path, sizeof(core_path));
406*b5893f02SDimitry Andric           if (FileSystem::Instance().Exists(core_file)) {
407*b5893f02SDimitry Andric             if (!FileSystem::Instance().Readable(core_file)) {
408435933ddSDimitry Andric               result.AppendMessageWithFormat(
409435933ddSDimitry Andric                   "Core file '%s' is not readable.\n", core_path);
4101c3bbb01SEd Maste               result.SetStatus(eReturnStatusFailed);
4111c3bbb01SEd Maste               return false;
4121c3bbb01SEd Maste             }
413ac7ddfbfSEd Maste             FileSpec core_file_dir;
414ac7ddfbfSEd Maste             core_file_dir.GetDirectory() = core_file.GetDirectory();
415ac7ddfbfSEd Maste             target_sp->GetExecutableSearchPaths().Append(core_file_dir);
416ac7ddfbfSEd Maste 
417435933ddSDimitry Andric             ProcessSP process_sp(target_sp->CreateProcess(
418435933ddSDimitry Andric                 m_interpreter.GetDebugger().GetListener(), llvm::StringRef(),
419435933ddSDimitry Andric                 &core_file));
420ac7ddfbfSEd Maste 
421435933ddSDimitry Andric             if (process_sp) {
4224ba319b5SDimitry Andric               // Seems weird that we Launch a core file, but that is what we
4234ba319b5SDimitry Andric               // do!
424ac7ddfbfSEd Maste               error = process_sp->LoadCore();
425ac7ddfbfSEd Maste 
426435933ddSDimitry Andric               if (error.Fail()) {
427435933ddSDimitry Andric                 result.AppendError(
428435933ddSDimitry Andric                     error.AsCString("can't find plug-in for core file"));
429ac7ddfbfSEd Maste                 result.SetStatus(eReturnStatusFailed);
430ac7ddfbfSEd Maste                 return false;
431435933ddSDimitry Andric               } else {
432435933ddSDimitry Andric                 result.AppendMessageWithFormat(
433435933ddSDimitry Andric                     "Core file '%s' (%s) was loaded.\n", core_path,
434435933ddSDimitry Andric                     target_sp->GetArchitecture().GetArchitectureName());
435ac7ddfbfSEd Maste                 result.SetStatus(eReturnStatusSuccessFinishNoResult);
436ac7ddfbfSEd Maste               }
437435933ddSDimitry Andric             } else {
438435933ddSDimitry Andric               result.AppendErrorWithFormat(
439435933ddSDimitry Andric                   "Unable to find process plug-in for core file '%s'\n",
440435933ddSDimitry Andric                   core_path);
441ac7ddfbfSEd Maste               result.SetStatus(eReturnStatusFailed);
442ac7ddfbfSEd Maste             }
443435933ddSDimitry Andric           } else {
444435933ddSDimitry Andric             result.AppendErrorWithFormat("Core file '%s' does not exist\n",
445435933ddSDimitry Andric                                          core_path);
446ac7ddfbfSEd Maste             result.SetStatus(eReturnStatusFailed);
447ac7ddfbfSEd Maste           }
448435933ddSDimitry Andric         } else {
449435933ddSDimitry Andric           result.AppendMessageWithFormat(
450435933ddSDimitry Andric               "Current executable set to '%s' (%s).\n", file_path,
451435933ddSDimitry Andric               target_sp->GetArchitecture().GetArchitectureName());
452ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusSuccessFinishNoResult);
453ac7ddfbfSEd Maste         }
454435933ddSDimitry Andric       } else {
455ac7ddfbfSEd Maste         result.AppendError(error.AsCString());
456ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
457ac7ddfbfSEd Maste       }
458435933ddSDimitry Andric     } else {
459435933ddSDimitry Andric       result.AppendErrorWithFormat("'%s' takes exactly one executable path "
460435933ddSDimitry Andric                                    "argument, or use the --core option.\n",
461435933ddSDimitry Andric                                    m_cmd_name.c_str());
462ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
463ac7ddfbfSEd Maste     }
464ac7ddfbfSEd Maste     return result.Succeeded();
465ac7ddfbfSEd Maste   }
466ac7ddfbfSEd Maste 
467ac7ddfbfSEd Maste private:
468ac7ddfbfSEd Maste   OptionGroupOptions m_option_group;
469ac7ddfbfSEd Maste   OptionGroupArchitecture m_arch_option;
470ac7ddfbfSEd Maste   OptionGroupFile m_core_file;
47135617911SEd Maste   OptionGroupFile m_platform_path;
472ac7ddfbfSEd Maste   OptionGroupFile m_symbol_file;
473ac7ddfbfSEd Maste   OptionGroupFile m_remote_file;
474*b5893f02SDimitry Andric   OptionGroupDependents m_add_dependents;
475ac7ddfbfSEd Maste };
476ac7ddfbfSEd Maste 
477ac7ddfbfSEd Maste #pragma mark CommandObjectTargetList
478ac7ddfbfSEd Maste 
479ac7ddfbfSEd Maste //----------------------------------------------------------------------
480ac7ddfbfSEd Maste // "target list"
481ac7ddfbfSEd Maste //----------------------------------------------------------------------
482ac7ddfbfSEd Maste 
483435933ddSDimitry Andric class CommandObjectTargetList : public CommandObjectParsed {
484ac7ddfbfSEd Maste public:
CommandObjectTargetList(CommandInterpreter & interpreter)485435933ddSDimitry Andric   CommandObjectTargetList(CommandInterpreter &interpreter)
486435933ddSDimitry Andric       : CommandObjectParsed(
487435933ddSDimitry Andric             interpreter, "target list",
488435933ddSDimitry Andric             "List all current targets in the current debug session.", nullptr) {
489ac7ddfbfSEd Maste   }
490ac7ddfbfSEd Maste 
4914bb0738eSEd Maste   ~CommandObjectTargetList() override = default;
492ac7ddfbfSEd Maste 
493ac7ddfbfSEd Maste protected:
DoExecute(Args & args,CommandReturnObject & result)494435933ddSDimitry Andric   bool DoExecute(Args &args, CommandReturnObject &result) override {
495435933ddSDimitry Andric     if (args.GetArgumentCount() == 0) {
496ac7ddfbfSEd Maste       Stream &strm = result.GetOutputStream();
497ac7ddfbfSEd Maste 
498ac7ddfbfSEd Maste       bool show_stopped_process_status = false;
499435933ddSDimitry Andric       if (DumpTargetList(m_interpreter.GetDebugger().GetTargetList(),
500435933ddSDimitry Andric                          show_stopped_process_status, strm) == 0) {
501ac7ddfbfSEd Maste         strm.PutCString("No targets.\n");
502ac7ddfbfSEd Maste       }
503ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusSuccessFinishResult);
504435933ddSDimitry Andric     } else {
505ac7ddfbfSEd Maste       result.AppendError("the 'target list' command takes no arguments\n");
506ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
507ac7ddfbfSEd Maste     }
508ac7ddfbfSEd Maste     return result.Succeeded();
509ac7ddfbfSEd Maste   }
510ac7ddfbfSEd Maste };
511ac7ddfbfSEd Maste 
512ac7ddfbfSEd Maste #pragma mark CommandObjectTargetSelect
513ac7ddfbfSEd Maste 
514ac7ddfbfSEd Maste //----------------------------------------------------------------------
515ac7ddfbfSEd Maste // "target select"
516ac7ddfbfSEd Maste //----------------------------------------------------------------------
517ac7ddfbfSEd Maste 
518435933ddSDimitry Andric class CommandObjectTargetSelect : public CommandObjectParsed {
519ac7ddfbfSEd Maste public:
CommandObjectTargetSelect(CommandInterpreter & interpreter)520435933ddSDimitry Andric   CommandObjectTargetSelect(CommandInterpreter &interpreter)
521435933ddSDimitry Andric       : CommandObjectParsed(
522435933ddSDimitry Andric             interpreter, "target select",
523435933ddSDimitry Andric             "Select a target as the current target by target index.", nullptr) {
524ac7ddfbfSEd Maste   }
525ac7ddfbfSEd Maste 
5264bb0738eSEd Maste   ~CommandObjectTargetSelect() override = default;
527ac7ddfbfSEd Maste 
528ac7ddfbfSEd Maste protected:
DoExecute(Args & args,CommandReturnObject & result)529435933ddSDimitry Andric   bool DoExecute(Args &args, CommandReturnObject &result) override {
530435933ddSDimitry Andric     if (args.GetArgumentCount() == 1) {
531ac7ddfbfSEd Maste       bool success = false;
532ac7ddfbfSEd Maste       const char *target_idx_arg = args.GetArgumentAtIndex(0);
533435933ddSDimitry Andric       uint32_t target_idx =
534435933ddSDimitry Andric           StringConvert::ToUInt32(target_idx_arg, UINT32_MAX, 0, &success);
535435933ddSDimitry Andric       if (success) {
536ac7ddfbfSEd Maste         TargetList &target_list = m_interpreter.GetDebugger().GetTargetList();
537ac7ddfbfSEd Maste         const uint32_t num_targets = target_list.GetNumTargets();
538435933ddSDimitry Andric         if (target_idx < num_targets) {
539ac7ddfbfSEd Maste           TargetSP target_sp(target_list.GetTargetAtIndex(target_idx));
540435933ddSDimitry Andric           if (target_sp) {
541ac7ddfbfSEd Maste             Stream &strm = result.GetOutputStream();
542ac7ddfbfSEd Maste             target_list.SetSelectedTarget(target_sp.get());
543ac7ddfbfSEd Maste             bool show_stopped_process_status = false;
544ac7ddfbfSEd Maste             DumpTargetList(target_list, show_stopped_process_status, strm);
545ac7ddfbfSEd Maste             result.SetStatus(eReturnStatusSuccessFinishResult);
546435933ddSDimitry Andric           } else {
547435933ddSDimitry Andric             result.AppendErrorWithFormat("target #%u is NULL in target list\n",
548435933ddSDimitry Andric                                          target_idx);
549ac7ddfbfSEd Maste             result.SetStatus(eReturnStatusFailed);
550ac7ddfbfSEd Maste           }
551435933ddSDimitry Andric         } else {
552435933ddSDimitry Andric           if (num_targets > 0) {
553435933ddSDimitry Andric             result.AppendErrorWithFormat(
554435933ddSDimitry Andric                 "index %u is out of range, valid target indexes are 0 - %u\n",
555435933ddSDimitry Andric                 target_idx, num_targets - 1);
556435933ddSDimitry Andric           } else {
557435933ddSDimitry Andric             result.AppendErrorWithFormat(
558435933ddSDimitry Andric                 "index %u is out of range since there are no active targets\n",
5590127ef0fSEd Maste                 target_idx);
5600127ef0fSEd Maste           }
561ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusFailed);
562ac7ddfbfSEd Maste         }
563435933ddSDimitry Andric       } else {
564435933ddSDimitry Andric         result.AppendErrorWithFormat("invalid index string value '%s'\n",
565435933ddSDimitry Andric                                      target_idx_arg);
566ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
567ac7ddfbfSEd Maste       }
568435933ddSDimitry Andric     } else {
569435933ddSDimitry Andric       result.AppendError(
570435933ddSDimitry Andric           "'target select' takes a single argument: a target index\n");
571ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
572ac7ddfbfSEd Maste     }
573ac7ddfbfSEd Maste     return result.Succeeded();
574ac7ddfbfSEd Maste   }
575ac7ddfbfSEd Maste };
576ac7ddfbfSEd Maste 
577ac7ddfbfSEd Maste #pragma mark CommandObjectTargetSelect
578ac7ddfbfSEd Maste 
579ac7ddfbfSEd Maste //----------------------------------------------------------------------
580ac7ddfbfSEd Maste // "target delete"
581ac7ddfbfSEd Maste //----------------------------------------------------------------------
582ac7ddfbfSEd Maste 
583435933ddSDimitry Andric class CommandObjectTargetDelete : public CommandObjectParsed {
584ac7ddfbfSEd Maste public:
CommandObjectTargetDelete(CommandInterpreter & interpreter)585435933ddSDimitry Andric   CommandObjectTargetDelete(CommandInterpreter &interpreter)
586435933ddSDimitry Andric       : CommandObjectParsed(interpreter, "target delete",
587ac7ddfbfSEd Maste                             "Delete one or more targets by target index.",
5884bb0738eSEd Maste                             nullptr),
589435933ddSDimitry Andric         m_option_group(), m_all_option(LLDB_OPT_SET_1, false, "all", 'a',
590435933ddSDimitry Andric                                        "Delete all targets.", false, true),
5911c3bbb01SEd Maste         m_cleanup_option(
592435933ddSDimitry Andric             LLDB_OPT_SET_1, false, "clean", 'c',
593435933ddSDimitry Andric             "Perform extra cleanup to minimize memory consumption after "
594435933ddSDimitry Andric             "deleting the target.  "
595435933ddSDimitry Andric             "By default, LLDB will keep in memory any modules previously "
596435933ddSDimitry Andric             "loaded by the target as well "
597435933ddSDimitry Andric             "as all of its debug info.  Specifying --clean will unload all of "
598435933ddSDimitry Andric             "these shared modules and "
5991c3bbb01SEd Maste             "cause them to be reparsed again the next time the target is run",
600435933ddSDimitry Andric             false, true) {
6011c3bbb01SEd Maste     m_option_group.Append(&m_all_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
602ac7ddfbfSEd Maste     m_option_group.Append(&m_cleanup_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
603ac7ddfbfSEd Maste     m_option_group.Finalize();
604ac7ddfbfSEd Maste   }
605ac7ddfbfSEd Maste 
6064bb0738eSEd Maste   ~CommandObjectTargetDelete() override = default;
607ac7ddfbfSEd Maste 
GetOptions()608435933ddSDimitry Andric   Options *GetOptions() override { return &m_option_group; }
609ac7ddfbfSEd Maste 
610ac7ddfbfSEd Maste protected:
DoExecute(Args & args,CommandReturnObject & result)611435933ddSDimitry Andric   bool DoExecute(Args &args, CommandReturnObject &result) override {
612ac7ddfbfSEd Maste     const size_t argc = args.GetArgumentCount();
613ac7ddfbfSEd Maste     std::vector<TargetSP> delete_target_list;
614ac7ddfbfSEd Maste     TargetList &target_list = m_interpreter.GetDebugger().GetTargetList();
615ac7ddfbfSEd Maste     TargetSP target_sp;
6161c3bbb01SEd Maste 
617435933ddSDimitry Andric     if (m_all_option.GetOptionValue()) {
6181c3bbb01SEd Maste       for (int i = 0; i < target_list.GetNumTargets(); ++i)
6191c3bbb01SEd Maste         delete_target_list.push_back(target_list.GetTargetAtIndex(i));
620435933ddSDimitry Andric     } else if (argc > 0) {
621ac7ddfbfSEd Maste       const uint32_t num_targets = target_list.GetNumTargets();
622ac7ddfbfSEd Maste       // Bail out if don't have any targets.
623ac7ddfbfSEd Maste       if (num_targets == 0) {
624ac7ddfbfSEd Maste         result.AppendError("no targets to delete");
625ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
6261c3bbb01SEd Maste         return false;
627ac7ddfbfSEd Maste       }
628ac7ddfbfSEd Maste 
629435933ddSDimitry Andric       for (auto &entry : args.entries()) {
630435933ddSDimitry Andric         uint32_t target_idx;
631435933ddSDimitry Andric         if (entry.ref.getAsInteger(0, target_idx)) {
632435933ddSDimitry Andric           result.AppendErrorWithFormat("invalid target index '%s'\n",
633435933ddSDimitry Andric                                        entry.c_str());
6341c3bbb01SEd Maste           result.SetStatus(eReturnStatusFailed);
6351c3bbb01SEd Maste           return false;
6361c3bbb01SEd Maste         }
637435933ddSDimitry Andric         if (target_idx < num_targets) {
638ac7ddfbfSEd Maste           target_sp = target_list.GetTargetAtIndex(target_idx);
639435933ddSDimitry Andric           if (target_sp) {
640ac7ddfbfSEd Maste             delete_target_list.push_back(target_sp);
641ac7ddfbfSEd Maste             continue;
642ac7ddfbfSEd Maste           }
643ac7ddfbfSEd Maste         }
644ac7ddfbfSEd Maste         if (num_targets > 1)
645435933ddSDimitry Andric           result.AppendErrorWithFormat("target index %u is out of range, valid "
646435933ddSDimitry Andric                                        "target indexes are 0 - %u\n",
647435933ddSDimitry Andric                                        target_idx, num_targets - 1);
648ac7ddfbfSEd Maste         else
649435933ddSDimitry Andric           result.AppendErrorWithFormat(
650435933ddSDimitry Andric               "target index %u is out of range, the only valid index is 0\n",
651ac7ddfbfSEd Maste               target_idx);
652ac7ddfbfSEd Maste 
653ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
6541c3bbb01SEd Maste         return false;
655ac7ddfbfSEd Maste       }
656435933ddSDimitry Andric     } else {
657ac7ddfbfSEd Maste       target_sp = target_list.GetSelectedTarget();
658435933ddSDimitry Andric       if (!target_sp) {
659ac7ddfbfSEd Maste         result.AppendErrorWithFormat("no target is currently selected\n");
660ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
6611c3bbb01SEd Maste         return false;
662ac7ddfbfSEd Maste       }
6631c3bbb01SEd Maste       delete_target_list.push_back(target_sp);
664ac7ddfbfSEd Maste     }
6651c3bbb01SEd Maste 
666ac7ddfbfSEd Maste     const size_t num_targets_to_delete = delete_target_list.size();
667435933ddSDimitry Andric     for (size_t idx = 0; idx < num_targets_to_delete; ++idx) {
668ac7ddfbfSEd Maste       target_sp = delete_target_list[idx];
669ac7ddfbfSEd Maste       target_list.DeleteTarget(target_sp);
670ac7ddfbfSEd Maste       target_sp->Destroy();
671ac7ddfbfSEd Maste     }
6724ba319b5SDimitry Andric     // If "--clean" was specified, prune any orphaned shared modules from the
6734ba319b5SDimitry Andric     // global shared module list
674435933ddSDimitry Andric     if (m_cleanup_option.GetOptionValue()) {
675ac7ddfbfSEd Maste       const bool mandatory = true;
676ac7ddfbfSEd Maste       ModuleList::RemoveOrphanSharedModules(mandatory);
677ac7ddfbfSEd Maste     }
678435933ddSDimitry Andric     result.GetOutputStream().Printf("%u targets deleted.\n",
679435933ddSDimitry Andric                                     (uint32_t)num_targets_to_delete);
680ac7ddfbfSEd Maste     result.SetStatus(eReturnStatusSuccessFinishResult);
681ac7ddfbfSEd Maste 
6821c3bbb01SEd Maste     return true;
683ac7ddfbfSEd Maste   }
684ac7ddfbfSEd Maste 
685ac7ddfbfSEd Maste   OptionGroupOptions m_option_group;
6861c3bbb01SEd Maste   OptionGroupBoolean m_all_option;
687ac7ddfbfSEd Maste   OptionGroupBoolean m_cleanup_option;
688ac7ddfbfSEd Maste };
689ac7ddfbfSEd Maste 
690ac7ddfbfSEd Maste #pragma mark CommandObjectTargetVariable
691ac7ddfbfSEd Maste 
692ac7ddfbfSEd Maste //----------------------------------------------------------------------
693ac7ddfbfSEd Maste // "target variable"
694ac7ddfbfSEd Maste //----------------------------------------------------------------------
695ac7ddfbfSEd Maste 
696435933ddSDimitry Andric class CommandObjectTargetVariable : public CommandObjectParsed {
6970127ef0fSEd Maste   static const uint32_t SHORT_OPTION_FILE = 0x66696c65; // 'file'
6980127ef0fSEd Maste   static const uint32_t SHORT_OPTION_SHLB = 0x73686c62; // 'shlb'
6990127ef0fSEd Maste 
700ac7ddfbfSEd Maste public:
CommandObjectTargetVariable(CommandInterpreter & interpreter)7014bb0738eSEd Maste   CommandObjectTargetVariable(CommandInterpreter &interpreter)
7024bb0738eSEd Maste       : CommandObjectParsed(interpreter, "target variable",
703435933ddSDimitry Andric                             "Read global variables for the current target, "
704435933ddSDimitry Andric                             "before or while running a process.",
7054bb0738eSEd Maste                             nullptr, eCommandRequiresTarget),
706435933ddSDimitry Andric         m_option_group(),
707ac7ddfbfSEd Maste         m_option_variable(false), // Don't include frame options
708ac7ddfbfSEd Maste         m_option_format(eFormatDefault),
709435933ddSDimitry Andric         m_option_compile_units(LLDB_OPT_SET_1, false, "file", SHORT_OPTION_FILE,
710435933ddSDimitry Andric                                0, eArgTypeFilename,
711435933ddSDimitry Andric                                "A basename or fullpath to a file that contains "
712435933ddSDimitry Andric                                "global variables. This option can be "
7134bb0738eSEd Maste                                "specified multiple times."),
714435933ddSDimitry Andric         m_option_shared_libraries(
715435933ddSDimitry Andric             LLDB_OPT_SET_1, false, "shlib", SHORT_OPTION_SHLB, 0,
716435933ddSDimitry Andric             eArgTypeFilename,
717435933ddSDimitry Andric             "A basename or fullpath to a shared library to use in the search "
718435933ddSDimitry Andric             "for global "
7194bb0738eSEd Maste             "variables. This option can be specified multiple times."),
720435933ddSDimitry Andric         m_varobj_options() {
721ac7ddfbfSEd Maste     CommandArgumentEntry arg;
722ac7ddfbfSEd Maste     CommandArgumentData var_name_arg;
723ac7ddfbfSEd Maste 
724ac7ddfbfSEd Maste     // Define the first (and only) variant of this arg.
725ac7ddfbfSEd Maste     var_name_arg.arg_type = eArgTypeVarName;
726ac7ddfbfSEd Maste     var_name_arg.arg_repetition = eArgRepeatPlus;
727ac7ddfbfSEd Maste 
728435933ddSDimitry Andric     // There is only one variant this argument could be; put it into the
729435933ddSDimitry Andric     // argument entry.
730ac7ddfbfSEd Maste     arg.push_back(var_name_arg);
731ac7ddfbfSEd Maste 
732ac7ddfbfSEd Maste     // Push the data for the first argument into the m_arguments vector.
733ac7ddfbfSEd Maste     m_arguments.push_back(arg);
734ac7ddfbfSEd Maste 
735ac7ddfbfSEd Maste     m_option_group.Append(&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
736ac7ddfbfSEd Maste     m_option_group.Append(&m_option_variable, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
737435933ddSDimitry Andric     m_option_group.Append(&m_option_format,
738435933ddSDimitry Andric                           OptionGroupFormat::OPTION_GROUP_FORMAT |
739435933ddSDimitry Andric                               OptionGroupFormat::OPTION_GROUP_GDB_FMT,
740435933ddSDimitry Andric                           LLDB_OPT_SET_1);
741435933ddSDimitry Andric     m_option_group.Append(&m_option_compile_units, LLDB_OPT_SET_ALL,
742435933ddSDimitry Andric                           LLDB_OPT_SET_1);
743435933ddSDimitry Andric     m_option_group.Append(&m_option_shared_libraries, LLDB_OPT_SET_ALL,
744435933ddSDimitry Andric                           LLDB_OPT_SET_1);
745ac7ddfbfSEd Maste     m_option_group.Finalize();
746ac7ddfbfSEd Maste   }
747ac7ddfbfSEd Maste 
7484bb0738eSEd Maste   ~CommandObjectTargetVariable() override = default;
749ac7ddfbfSEd Maste 
DumpValueObject(Stream & s,VariableSP & var_sp,ValueObjectSP & valobj_sp,const char * root_name)750435933ddSDimitry Andric   void DumpValueObject(Stream &s, VariableSP &var_sp, ValueObjectSP &valobj_sp,
751435933ddSDimitry Andric                        const char *root_name) {
75235617911SEd Maste     DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions());
753ac7ddfbfSEd Maste 
7544bb0738eSEd Maste     if (!valobj_sp->GetTargetSP()->GetDisplayRuntimeSupportValues() &&
7554bb0738eSEd Maste         valobj_sp->IsRuntimeSupportValue())
7561c3bbb01SEd Maste       return;
7571c3bbb01SEd Maste 
758435933ddSDimitry Andric     switch (var_sp->GetScope()) {
759ac7ddfbfSEd Maste     case eValueTypeVariableGlobal:
760ac7ddfbfSEd Maste       if (m_option_variable.show_scope)
761ac7ddfbfSEd Maste         s.PutCString("GLOBAL: ");
762ac7ddfbfSEd Maste       break;
763ac7ddfbfSEd Maste 
764ac7ddfbfSEd Maste     case eValueTypeVariableStatic:
765ac7ddfbfSEd Maste       if (m_option_variable.show_scope)
766ac7ddfbfSEd Maste         s.PutCString("STATIC: ");
767ac7ddfbfSEd Maste       break;
768ac7ddfbfSEd Maste 
769ac7ddfbfSEd Maste     case eValueTypeVariableArgument:
770ac7ddfbfSEd Maste       if (m_option_variable.show_scope)
771ac7ddfbfSEd Maste         s.PutCString("   ARG: ");
772ac7ddfbfSEd Maste       break;
773ac7ddfbfSEd Maste 
774ac7ddfbfSEd Maste     case eValueTypeVariableLocal:
775ac7ddfbfSEd Maste       if (m_option_variable.show_scope)
776ac7ddfbfSEd Maste         s.PutCString(" LOCAL: ");
777ac7ddfbfSEd Maste       break;
778ac7ddfbfSEd Maste 
7794bb0738eSEd Maste     case eValueTypeVariableThreadLocal:
7804bb0738eSEd Maste       if (m_option_variable.show_scope)
7814bb0738eSEd Maste         s.PutCString("THREAD: ");
7824bb0738eSEd Maste       break;
7834bb0738eSEd Maste 
784ac7ddfbfSEd Maste     default:
785ac7ddfbfSEd Maste       break;
786ac7ddfbfSEd Maste     }
787ac7ddfbfSEd Maste 
788435933ddSDimitry Andric     if (m_option_variable.show_decl) {
789ac7ddfbfSEd Maste       bool show_fullpaths = false;
790ac7ddfbfSEd Maste       bool show_module = true;
791ac7ddfbfSEd Maste       if (var_sp->DumpDeclaration(&s, show_fullpaths, show_module))
792ac7ddfbfSEd Maste         s.PutCString(": ");
793ac7ddfbfSEd Maste     }
794ac7ddfbfSEd Maste 
795ac7ddfbfSEd Maste     const Format format = m_option_format.GetFormat();
796ac7ddfbfSEd Maste     if (format != eFormatDefault)
797ac7ddfbfSEd Maste       options.SetFormat(format);
798ac7ddfbfSEd Maste 
799ac7ddfbfSEd Maste     options.SetRootValueObjectName(root_name);
800ac7ddfbfSEd Maste 
80135617911SEd Maste     valobj_sp->Dump(s, options);
802ac7ddfbfSEd Maste   }
803ac7ddfbfSEd Maste 
GetVariableCallback(void * baton,const char * name,VariableList & variable_list)804435933ddSDimitry Andric   static size_t GetVariableCallback(void *baton, const char *name,
805435933ddSDimitry Andric                                     VariableList &variable_list) {
806ac7ddfbfSEd Maste     Target *target = static_cast<Target *>(baton);
807435933ddSDimitry Andric     if (target) {
8084ba319b5SDimitry Andric       return target->GetImages().FindGlobalVariables(ConstString(name),
809435933ddSDimitry Andric                                                      UINT32_MAX, variable_list);
810ac7ddfbfSEd Maste     }
811ac7ddfbfSEd Maste     return 0;
812ac7ddfbfSEd Maste   }
813ac7ddfbfSEd Maste 
GetOptions()814435933ddSDimitry Andric   Options *GetOptions() override { return &m_option_group; }
815ac7ddfbfSEd Maste 
816ac7ddfbfSEd Maste protected:
DumpGlobalVariableList(const ExecutionContext & exe_ctx,const SymbolContext & sc,const VariableList & variable_list,Stream & s)817435933ddSDimitry Andric   void DumpGlobalVariableList(const ExecutionContext &exe_ctx,
818435933ddSDimitry Andric                               const SymbolContext &sc,
819435933ddSDimitry Andric                               const VariableList &variable_list, Stream &s) {
820ac7ddfbfSEd Maste     size_t count = variable_list.GetSize();
821435933ddSDimitry Andric     if (count > 0) {
822435933ddSDimitry Andric       if (sc.module_sp) {
823435933ddSDimitry Andric         if (sc.comp_unit) {
824ac7ddfbfSEd Maste           s.Printf("Global variables for %s in %s:\n",
825ac7ddfbfSEd Maste                    sc.comp_unit->GetPath().c_str(),
826ac7ddfbfSEd Maste                    sc.module_sp->GetFileSpec().GetPath().c_str());
827435933ddSDimitry Andric         } else {
828ac7ddfbfSEd Maste           s.Printf("Global variables for %s\n",
829ac7ddfbfSEd Maste                    sc.module_sp->GetFileSpec().GetPath().c_str());
830ac7ddfbfSEd Maste         }
831435933ddSDimitry Andric       } else if (sc.comp_unit) {
832435933ddSDimitry Andric         s.Printf("Global variables for %s\n", sc.comp_unit->GetPath().c_str());
833ac7ddfbfSEd Maste       }
834ac7ddfbfSEd Maste 
835435933ddSDimitry Andric       for (uint32_t i = 0; i < count; ++i) {
836ac7ddfbfSEd Maste         VariableSP var_sp(variable_list.GetVariableAtIndex(i));
837435933ddSDimitry Andric         if (var_sp) {
838435933ddSDimitry Andric           ValueObjectSP valobj_sp(ValueObjectVariable::Create(
839435933ddSDimitry Andric               exe_ctx.GetBestExecutionContextScope(), var_sp));
840ac7ddfbfSEd Maste 
841ac7ddfbfSEd Maste           if (valobj_sp)
842435933ddSDimitry Andric             DumpValueObject(s, var_sp, valobj_sp,
843435933ddSDimitry Andric                             var_sp->GetName().GetCString());
844ac7ddfbfSEd Maste         }
845ac7ddfbfSEd Maste       }
846ac7ddfbfSEd Maste     }
847ac7ddfbfSEd Maste   }
8484bb0738eSEd Maste 
DoExecute(Args & args,CommandReturnObject & result)849435933ddSDimitry Andric   bool DoExecute(Args &args, CommandReturnObject &result) override {
850ac7ddfbfSEd Maste     Target *target = m_exe_ctx.GetTargetPtr();
851ac7ddfbfSEd Maste     const size_t argc = args.GetArgumentCount();
852ac7ddfbfSEd Maste     Stream &s = result.GetOutputStream();
853ac7ddfbfSEd Maste 
854435933ddSDimitry Andric     if (argc > 0) {
855ac7ddfbfSEd Maste 
856435933ddSDimitry Andric       // TODO: Convert to entry-based iteration.  Requires converting
857435933ddSDimitry Andric       // DumpValueObject.
858435933ddSDimitry Andric       for (size_t idx = 0; idx < argc; ++idx) {
859ac7ddfbfSEd Maste         VariableList variable_list;
860ac7ddfbfSEd Maste         ValueObjectList valobj_list;
861ac7ddfbfSEd Maste 
862ac7ddfbfSEd Maste         const char *arg = args.GetArgumentAtIndex(idx);
863ac7ddfbfSEd Maste         size_t matches = 0;
864ac7ddfbfSEd Maste         bool use_var_name = false;
865435933ddSDimitry Andric         if (m_option_variable.use_regex) {
866435933ddSDimitry Andric           RegularExpression regex(llvm::StringRef::withNullAsEmpty(arg));
867435933ddSDimitry Andric           if (!regex.IsValid()) {
868435933ddSDimitry Andric             result.GetErrorStream().Printf(
869435933ddSDimitry Andric                 "error: invalid regular expression: '%s'\n", arg);
870ac7ddfbfSEd Maste             result.SetStatus(eReturnStatusFailed);
871ac7ddfbfSEd Maste             return false;
872ac7ddfbfSEd Maste           }
873ac7ddfbfSEd Maste           use_var_name = true;
8744ba319b5SDimitry Andric           matches = target->GetImages().FindGlobalVariables(regex, UINT32_MAX,
8754ba319b5SDimitry Andric                                                             variable_list);
876435933ddSDimitry Andric         } else {
8775517e702SDimitry Andric           Status error(Variable::GetValuesForVariableExpressionPath(
878435933ddSDimitry Andric               arg, m_exe_ctx.GetBestExecutionContextScope(),
879435933ddSDimitry Andric               GetVariableCallback, target, variable_list, valobj_list));
880ac7ddfbfSEd Maste           matches = variable_list.GetSize();
881ac7ddfbfSEd Maste         }
882ac7ddfbfSEd Maste 
883435933ddSDimitry Andric         if (matches == 0) {
884435933ddSDimitry Andric           result.GetErrorStream().Printf(
885435933ddSDimitry Andric               "error: can't find global variable '%s'\n", arg);
886ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusFailed);
887ac7ddfbfSEd Maste           return false;
888435933ddSDimitry Andric         } else {
889435933ddSDimitry Andric           for (uint32_t global_idx = 0; global_idx < matches; ++global_idx) {
890ac7ddfbfSEd Maste             VariableSP var_sp(variable_list.GetVariableAtIndex(global_idx));
891435933ddSDimitry Andric             if (var_sp) {
892435933ddSDimitry Andric               ValueObjectSP valobj_sp(
893435933ddSDimitry Andric                   valobj_list.GetValueObjectAtIndex(global_idx));
894ac7ddfbfSEd Maste               if (!valobj_sp)
895435933ddSDimitry Andric                 valobj_sp = ValueObjectVariable::Create(
896435933ddSDimitry Andric                     m_exe_ctx.GetBestExecutionContextScope(), var_sp);
897ac7ddfbfSEd Maste 
898ac7ddfbfSEd Maste               if (valobj_sp)
899435933ddSDimitry Andric                 DumpValueObject(s, var_sp, valobj_sp,
900435933ddSDimitry Andric                                 use_var_name ? var_sp->GetName().GetCString()
901435933ddSDimitry Andric                                              : arg);
902ac7ddfbfSEd Maste             }
903ac7ddfbfSEd Maste           }
904ac7ddfbfSEd Maste         }
905ac7ddfbfSEd Maste       }
906435933ddSDimitry Andric     } else {
907435933ddSDimitry Andric       const FileSpecList &compile_units =
908435933ddSDimitry Andric           m_option_compile_units.GetOptionValue().GetCurrentValue();
909435933ddSDimitry Andric       const FileSpecList &shlibs =
910435933ddSDimitry Andric           m_option_shared_libraries.GetOptionValue().GetCurrentValue();
911ac7ddfbfSEd Maste       SymbolContextList sc_list;
912ac7ddfbfSEd Maste       const size_t num_compile_units = compile_units.GetSize();
913ac7ddfbfSEd Maste       const size_t num_shlibs = shlibs.GetSize();
914435933ddSDimitry Andric       if (num_compile_units == 0 && num_shlibs == 0) {
915ac7ddfbfSEd Maste         bool success = false;
916ac7ddfbfSEd Maste         StackFrame *frame = m_exe_ctx.GetFramePtr();
9174bb0738eSEd Maste         CompileUnit *comp_unit = nullptr;
918435933ddSDimitry Andric         if (frame) {
919ac7ddfbfSEd Maste           SymbolContext sc = frame->GetSymbolContext(eSymbolContextCompUnit);
920435933ddSDimitry Andric           if (sc.comp_unit) {
921ac7ddfbfSEd Maste             const bool can_create = true;
922435933ddSDimitry Andric             VariableListSP comp_unit_varlist_sp(
923435933ddSDimitry Andric                 sc.comp_unit->GetVariableList(can_create));
924435933ddSDimitry Andric             if (comp_unit_varlist_sp) {
925ac7ddfbfSEd Maste               size_t count = comp_unit_varlist_sp->GetSize();
926435933ddSDimitry Andric               if (count > 0) {
927ac7ddfbfSEd Maste                 DumpGlobalVariableList(m_exe_ctx, sc, *comp_unit_varlist_sp, s);
928ac7ddfbfSEd Maste                 success = true;
929ac7ddfbfSEd Maste               }
930ac7ddfbfSEd Maste             }
931ac7ddfbfSEd Maste           }
932ac7ddfbfSEd Maste         }
933435933ddSDimitry Andric         if (!success) {
934435933ddSDimitry Andric           if (frame) {
935ac7ddfbfSEd Maste             if (comp_unit)
936435933ddSDimitry Andric               result.AppendErrorWithFormat(
937435933ddSDimitry Andric                   "no global variables in current compile unit: %s\n",
938ac7ddfbfSEd Maste                   comp_unit->GetPath().c_str());
939ac7ddfbfSEd Maste             else
940435933ddSDimitry Andric               result.AppendErrorWithFormat(
941435933ddSDimitry Andric                   "no debug information for frame %u\n",
942435933ddSDimitry Andric                   frame->GetFrameIndex());
943435933ddSDimitry Andric           } else
944435933ddSDimitry Andric             result.AppendError("'target variable' takes one or more global "
945435933ddSDimitry Andric                                "variable names as arguments\n");
946ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusFailed);
947ac7ddfbfSEd Maste         }
948435933ddSDimitry Andric       } else {
949ac7ddfbfSEd Maste         SymbolContextList sc_list;
950ac7ddfbfSEd Maste         const bool append = true;
951ac7ddfbfSEd Maste         // We have one or more compile unit or shlib
952435933ddSDimitry Andric         if (num_shlibs > 0) {
953435933ddSDimitry Andric           for (size_t shlib_idx = 0; shlib_idx < num_shlibs; ++shlib_idx) {
954ac7ddfbfSEd Maste             const FileSpec module_file(shlibs.GetFileSpecAtIndex(shlib_idx));
955ac7ddfbfSEd Maste             ModuleSpec module_spec(module_file);
956ac7ddfbfSEd Maste 
957435933ddSDimitry Andric             ModuleSP module_sp(
958435933ddSDimitry Andric                 target->GetImages().FindFirstModule(module_spec));
959435933ddSDimitry Andric             if (module_sp) {
960435933ddSDimitry Andric               if (num_compile_units > 0) {
961ac7ddfbfSEd Maste                 for (size_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
962435933ddSDimitry Andric                   module_sp->FindCompileUnits(
963435933ddSDimitry Andric                       compile_units.GetFileSpecAtIndex(cu_idx), append,
964435933ddSDimitry Andric                       sc_list);
965435933ddSDimitry Andric               } else {
966ac7ddfbfSEd Maste                 SymbolContext sc;
967ac7ddfbfSEd Maste                 sc.module_sp = module_sp;
968ac7ddfbfSEd Maste                 sc_list.Append(sc);
969ac7ddfbfSEd Maste               }
970435933ddSDimitry Andric             } else {
971ac7ddfbfSEd Maste               // Didn't find matching shlib/module in target...
972435933ddSDimitry Andric               result.AppendErrorWithFormat(
973435933ddSDimitry Andric                   "target doesn't contain the specified shared library: %s\n",
974ac7ddfbfSEd Maste                   module_file.GetPath().c_str());
975ac7ddfbfSEd Maste             }
976ac7ddfbfSEd Maste           }
977435933ddSDimitry Andric         } else {
978435933ddSDimitry Andric           // No shared libraries, we just want to find globals for the compile
979435933ddSDimitry Andric           // units files that were specified
980ac7ddfbfSEd Maste           for (size_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
981435933ddSDimitry Andric             target->GetImages().FindCompileUnits(
982435933ddSDimitry Andric                 compile_units.GetFileSpecAtIndex(cu_idx), append, sc_list);
983ac7ddfbfSEd Maste         }
984ac7ddfbfSEd Maste 
985ac7ddfbfSEd Maste         const uint32_t num_scs = sc_list.GetSize();
986435933ddSDimitry Andric         if (num_scs > 0) {
987ac7ddfbfSEd Maste           SymbolContext sc;
988435933ddSDimitry Andric           for (uint32_t sc_idx = 0; sc_idx < num_scs; ++sc_idx) {
989435933ddSDimitry Andric             if (sc_list.GetContextAtIndex(sc_idx, sc)) {
990435933ddSDimitry Andric               if (sc.comp_unit) {
991ac7ddfbfSEd Maste                 const bool can_create = true;
992435933ddSDimitry Andric                 VariableListSP comp_unit_varlist_sp(
993435933ddSDimitry Andric                     sc.comp_unit->GetVariableList(can_create));
994ac7ddfbfSEd Maste                 if (comp_unit_varlist_sp)
995435933ddSDimitry Andric                   DumpGlobalVariableList(m_exe_ctx, sc, *comp_unit_varlist_sp,
996435933ddSDimitry Andric                                          s);
997435933ddSDimitry Andric               } else if (sc.module_sp) {
998ac7ddfbfSEd Maste                 // Get all global variables for this module
999435933ddSDimitry Andric                 lldb_private::RegularExpression all_globals_regex(
1000435933ddSDimitry Andric                     llvm::StringRef(
1001435933ddSDimitry Andric                         ".")); // Any global with at least one character
1002ac7ddfbfSEd Maste                 VariableList variable_list;
10034ba319b5SDimitry Andric                 sc.module_sp->FindGlobalVariables(all_globals_regex, UINT32_MAX,
10044ba319b5SDimitry Andric                                                   variable_list);
1005ac7ddfbfSEd Maste                 DumpGlobalVariableList(m_exe_ctx, sc, variable_list, s);
1006ac7ddfbfSEd Maste               }
1007ac7ddfbfSEd Maste             }
1008ac7ddfbfSEd Maste           }
1009ac7ddfbfSEd Maste         }
1010ac7ddfbfSEd Maste       }
1011ac7ddfbfSEd Maste     }
1012ac7ddfbfSEd Maste 
1013435933ddSDimitry Andric     if (m_interpreter.TruncationWarningNecessary()) {
1014ac7ddfbfSEd Maste       result.GetOutputStream().Printf(m_interpreter.TruncationWarningText(),
1015ac7ddfbfSEd Maste                                       m_cmd_name.c_str());
1016ac7ddfbfSEd Maste       m_interpreter.TruncationWarningGiven();
1017ac7ddfbfSEd Maste     }
1018ac7ddfbfSEd Maste 
1019ac7ddfbfSEd Maste     return result.Succeeded();
1020ac7ddfbfSEd Maste   }
1021ac7ddfbfSEd Maste 
1022ac7ddfbfSEd Maste   OptionGroupOptions m_option_group;
1023ac7ddfbfSEd Maste   OptionGroupVariable m_option_variable;
1024ac7ddfbfSEd Maste   OptionGroupFormat m_option_format;
1025ac7ddfbfSEd Maste   OptionGroupFileList m_option_compile_units;
1026ac7ddfbfSEd Maste   OptionGroupFileList m_option_shared_libraries;
1027ac7ddfbfSEd Maste   OptionGroupValueObjectDisplay m_varobj_options;
1028ac7ddfbfSEd Maste };
1029ac7ddfbfSEd Maste 
1030ac7ddfbfSEd Maste #pragma mark CommandObjectTargetModulesSearchPathsAdd
1031ac7ddfbfSEd Maste 
1032435933ddSDimitry Andric class CommandObjectTargetModulesSearchPathsAdd : public CommandObjectParsed {
1033ac7ddfbfSEd Maste public:
CommandObjectTargetModulesSearchPathsAdd(CommandInterpreter & interpreter)1034435933ddSDimitry Andric   CommandObjectTargetModulesSearchPathsAdd(CommandInterpreter &interpreter)
1035435933ddSDimitry Andric       : CommandObjectParsed(interpreter, "target modules search-paths add",
1036435933ddSDimitry Andric                             "Add new image search paths substitution pairs to "
1037435933ddSDimitry Andric                             "the current target.",
1038435933ddSDimitry Andric                             nullptr) {
1039ac7ddfbfSEd Maste     CommandArgumentEntry arg;
1040ac7ddfbfSEd Maste     CommandArgumentData old_prefix_arg;
1041ac7ddfbfSEd Maste     CommandArgumentData new_prefix_arg;
1042ac7ddfbfSEd Maste 
1043ac7ddfbfSEd Maste     // Define the first variant of this arg pair.
1044ac7ddfbfSEd Maste     old_prefix_arg.arg_type = eArgTypeOldPathPrefix;
1045ac7ddfbfSEd Maste     old_prefix_arg.arg_repetition = eArgRepeatPairPlus;
1046ac7ddfbfSEd Maste 
1047ac7ddfbfSEd Maste     // Define the first variant of this arg pair.
1048ac7ddfbfSEd Maste     new_prefix_arg.arg_type = eArgTypeNewPathPrefix;
1049ac7ddfbfSEd Maste     new_prefix_arg.arg_repetition = eArgRepeatPairPlus;
1050ac7ddfbfSEd Maste 
10514ba319b5SDimitry Andric     // There are two required arguments that must always occur together, i.e.
10524ba319b5SDimitry Andric     // an argument "pair".  Because they must always occur together, they are
10534ba319b5SDimitry Andric     // treated as two variants of one argument rather than two independent
1054435933ddSDimitry Andric     // arguments.  Push them both into the first argument position for
1055435933ddSDimitry Andric     // m_arguments...
1056ac7ddfbfSEd Maste 
1057ac7ddfbfSEd Maste     arg.push_back(old_prefix_arg);
1058ac7ddfbfSEd Maste     arg.push_back(new_prefix_arg);
1059ac7ddfbfSEd Maste 
1060ac7ddfbfSEd Maste     m_arguments.push_back(arg);
1061ac7ddfbfSEd Maste   }
1062ac7ddfbfSEd Maste 
10634bb0738eSEd Maste   ~CommandObjectTargetModulesSearchPathsAdd() override = default;
1064ac7ddfbfSEd Maste 
1065ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)1066435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
1067ac7ddfbfSEd Maste     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1068435933ddSDimitry Andric     if (target) {
1069ac7ddfbfSEd Maste       const size_t argc = command.GetArgumentCount();
1070435933ddSDimitry Andric       if (argc & 1) {
1071ac7ddfbfSEd Maste         result.AppendError("add requires an even number of arguments\n");
1072ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
1073435933ddSDimitry Andric       } else {
1074435933ddSDimitry Andric         for (size_t i = 0; i < argc; i += 2) {
1075ac7ddfbfSEd Maste           const char *from = command.GetArgumentAtIndex(i);
1076ac7ddfbfSEd Maste           const char *to = command.GetArgumentAtIndex(i + 1);
1077ac7ddfbfSEd Maste 
1078435933ddSDimitry Andric           if (from[0] && to[0]) {
10799f2f44ceSEd Maste             Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
1080435933ddSDimitry Andric             if (log) {
1081435933ddSDimitry Andric               log->Printf("target modules search path adding ImageSearchPath "
1082435933ddSDimitry Andric                           "pair: '%s' -> '%s'",
10839f2f44ceSEd Maste                           from, to);
10849f2f44ceSEd Maste             }
1085ac7ddfbfSEd Maste             bool last_pair = ((argc - i) == 2);
1086435933ddSDimitry Andric             target->GetImageSearchPathList().Append(
1087435933ddSDimitry Andric                 ConstString(from), ConstString(to),
1088ac7ddfbfSEd Maste                 last_pair); // Notify if this is the last pair
1089ac7ddfbfSEd Maste             result.SetStatus(eReturnStatusSuccessFinishNoResult);
1090435933ddSDimitry Andric           } else {
1091ac7ddfbfSEd Maste             if (from[0])
1092ac7ddfbfSEd Maste               result.AppendError("<path-prefix> can't be empty\n");
1093ac7ddfbfSEd Maste             else
1094ac7ddfbfSEd Maste               result.AppendError("<new-path-prefix> can't be empty\n");
1095ac7ddfbfSEd Maste             result.SetStatus(eReturnStatusFailed);
1096ac7ddfbfSEd Maste           }
1097ac7ddfbfSEd Maste         }
1098ac7ddfbfSEd Maste       }
1099435933ddSDimitry Andric     } else {
1100ac7ddfbfSEd Maste       result.AppendError("invalid target\n");
1101ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1102ac7ddfbfSEd Maste     }
1103ac7ddfbfSEd Maste     return result.Succeeded();
1104ac7ddfbfSEd Maste   }
1105ac7ddfbfSEd Maste };
1106ac7ddfbfSEd Maste 
1107ac7ddfbfSEd Maste #pragma mark CommandObjectTargetModulesSearchPathsClear
1108ac7ddfbfSEd Maste 
1109435933ddSDimitry Andric class CommandObjectTargetModulesSearchPathsClear : public CommandObjectParsed {
1110ac7ddfbfSEd Maste public:
CommandObjectTargetModulesSearchPathsClear(CommandInterpreter & interpreter)1111435933ddSDimitry Andric   CommandObjectTargetModulesSearchPathsClear(CommandInterpreter &interpreter)
1112435933ddSDimitry Andric       : CommandObjectParsed(interpreter, "target modules search-paths clear",
1113435933ddSDimitry Andric                             "Clear all current image search path substitution "
1114435933ddSDimitry Andric                             "pairs from the current target.",
1115435933ddSDimitry Andric                             "target modules search-paths clear") {}
1116ac7ddfbfSEd Maste 
11174bb0738eSEd Maste   ~CommandObjectTargetModulesSearchPathsClear() override = default;
1118ac7ddfbfSEd Maste 
1119ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)1120435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
1121ac7ddfbfSEd Maste     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1122435933ddSDimitry Andric     if (target) {
1123ac7ddfbfSEd Maste       bool notify = true;
1124ac7ddfbfSEd Maste       target->GetImageSearchPathList().Clear(notify);
1125ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1126435933ddSDimitry Andric     } else {
1127ac7ddfbfSEd Maste       result.AppendError("invalid target\n");
1128ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1129ac7ddfbfSEd Maste     }
1130ac7ddfbfSEd Maste     return result.Succeeded();
1131ac7ddfbfSEd Maste   }
1132ac7ddfbfSEd Maste };
1133ac7ddfbfSEd Maste 
1134ac7ddfbfSEd Maste #pragma mark CommandObjectTargetModulesSearchPathsInsert
1135ac7ddfbfSEd Maste 
1136435933ddSDimitry Andric class CommandObjectTargetModulesSearchPathsInsert : public CommandObjectParsed {
1137ac7ddfbfSEd Maste public:
CommandObjectTargetModulesSearchPathsInsert(CommandInterpreter & interpreter)1138435933ddSDimitry Andric   CommandObjectTargetModulesSearchPathsInsert(CommandInterpreter &interpreter)
1139435933ddSDimitry Andric       : CommandObjectParsed(interpreter, "target modules search-paths insert",
1140435933ddSDimitry Andric                             "Insert a new image search path substitution pair "
1141435933ddSDimitry Andric                             "into the current target at the specified index.",
1142435933ddSDimitry Andric                             nullptr) {
1143ac7ddfbfSEd Maste     CommandArgumentEntry arg1;
1144ac7ddfbfSEd Maste     CommandArgumentEntry arg2;
1145ac7ddfbfSEd Maste     CommandArgumentData index_arg;
1146ac7ddfbfSEd Maste     CommandArgumentData old_prefix_arg;
1147ac7ddfbfSEd Maste     CommandArgumentData new_prefix_arg;
1148ac7ddfbfSEd Maste 
1149ac7ddfbfSEd Maste     // Define the first and only variant of this arg.
1150ac7ddfbfSEd Maste     index_arg.arg_type = eArgTypeIndex;
1151ac7ddfbfSEd Maste     index_arg.arg_repetition = eArgRepeatPlain;
1152ac7ddfbfSEd Maste 
1153ac7ddfbfSEd Maste     // Put the one and only variant into the first arg for m_arguments:
1154ac7ddfbfSEd Maste     arg1.push_back(index_arg);
1155ac7ddfbfSEd Maste 
1156ac7ddfbfSEd Maste     // Define the first variant of this arg pair.
1157ac7ddfbfSEd Maste     old_prefix_arg.arg_type = eArgTypeOldPathPrefix;
1158ac7ddfbfSEd Maste     old_prefix_arg.arg_repetition = eArgRepeatPairPlus;
1159ac7ddfbfSEd Maste 
1160ac7ddfbfSEd Maste     // Define the first variant of this arg pair.
1161ac7ddfbfSEd Maste     new_prefix_arg.arg_type = eArgTypeNewPathPrefix;
1162ac7ddfbfSEd Maste     new_prefix_arg.arg_repetition = eArgRepeatPairPlus;
1163ac7ddfbfSEd Maste 
11644ba319b5SDimitry Andric     // There are two required arguments that must always occur together, i.e.
11654ba319b5SDimitry Andric     // an argument "pair".  Because they must always occur together, they are
11664ba319b5SDimitry Andric     // treated as two variants of one argument rather than two independent
1167435933ddSDimitry Andric     // arguments.  Push them both into the same argument position for
1168435933ddSDimitry Andric     // m_arguments...
1169ac7ddfbfSEd Maste 
1170ac7ddfbfSEd Maste     arg2.push_back(old_prefix_arg);
1171ac7ddfbfSEd Maste     arg2.push_back(new_prefix_arg);
1172ac7ddfbfSEd Maste 
1173ac7ddfbfSEd Maste     // Add arguments to m_arguments.
1174ac7ddfbfSEd Maste     m_arguments.push_back(arg1);
1175ac7ddfbfSEd Maste     m_arguments.push_back(arg2);
1176ac7ddfbfSEd Maste   }
1177ac7ddfbfSEd Maste 
11784bb0738eSEd Maste   ~CommandObjectTargetModulesSearchPathsInsert() override = default;
1179ac7ddfbfSEd Maste 
1180ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)1181435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
1182ac7ddfbfSEd Maste     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1183435933ddSDimitry Andric     if (target) {
1184ac7ddfbfSEd Maste       size_t argc = command.GetArgumentCount();
11859f2f44ceSEd Maste       // check for at least 3 arguments and an odd number of parameters
1186435933ddSDimitry Andric       if (argc >= 3 && argc & 1) {
1187ac7ddfbfSEd Maste         bool success = false;
1188ac7ddfbfSEd Maste 
1189435933ddSDimitry Andric         uint32_t insert_idx = StringConvert::ToUInt32(
1190435933ddSDimitry Andric             command.GetArgumentAtIndex(0), UINT32_MAX, 0, &success);
1191ac7ddfbfSEd Maste 
1192435933ddSDimitry Andric         if (!success) {
1193435933ddSDimitry Andric           result.AppendErrorWithFormat(
1194435933ddSDimitry Andric               "<index> parameter is not an integer: '%s'.\n",
1195435933ddSDimitry Andric               command.GetArgumentAtIndex(0));
1196ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusFailed);
1197ac7ddfbfSEd Maste           return result.Succeeded();
1198ac7ddfbfSEd Maste         }
1199ac7ddfbfSEd Maste 
1200ac7ddfbfSEd Maste         // shift off the index
1201ac7ddfbfSEd Maste         command.Shift();
1202ac7ddfbfSEd Maste         argc = command.GetArgumentCount();
1203ac7ddfbfSEd Maste 
1204435933ddSDimitry Andric         for (uint32_t i = 0; i < argc; i += 2, ++insert_idx) {
1205ac7ddfbfSEd Maste           const char *from = command.GetArgumentAtIndex(i);
1206ac7ddfbfSEd Maste           const char *to = command.GetArgumentAtIndex(i + 1);
1207ac7ddfbfSEd Maste 
1208435933ddSDimitry Andric           if (from[0] && to[0]) {
1209ac7ddfbfSEd Maste             bool last_pair = ((argc - i) == 2);
1210435933ddSDimitry Andric             target->GetImageSearchPathList().Insert(
1211435933ddSDimitry Andric                 ConstString(from), ConstString(to), insert_idx, last_pair);
1212ac7ddfbfSEd Maste             result.SetStatus(eReturnStatusSuccessFinishNoResult);
1213435933ddSDimitry Andric           } else {
1214ac7ddfbfSEd Maste             if (from[0])
1215ac7ddfbfSEd Maste               result.AppendError("<path-prefix> can't be empty\n");
1216ac7ddfbfSEd Maste             else
1217ac7ddfbfSEd Maste               result.AppendError("<new-path-prefix> can't be empty\n");
1218ac7ddfbfSEd Maste             result.SetStatus(eReturnStatusFailed);
1219ac7ddfbfSEd Maste             return false;
1220ac7ddfbfSEd Maste           }
1221ac7ddfbfSEd Maste         }
1222435933ddSDimitry Andric       } else {
1223ac7ddfbfSEd Maste         result.AppendError("insert requires at least three arguments\n");
1224ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
1225ac7ddfbfSEd Maste         return result.Succeeded();
1226ac7ddfbfSEd Maste       }
1227ac7ddfbfSEd Maste 
1228435933ddSDimitry Andric     } else {
1229ac7ddfbfSEd Maste       result.AppendError("invalid target\n");
1230ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1231ac7ddfbfSEd Maste     }
1232ac7ddfbfSEd Maste     return result.Succeeded();
1233ac7ddfbfSEd Maste   }
1234ac7ddfbfSEd Maste };
1235ac7ddfbfSEd Maste 
1236ac7ddfbfSEd Maste #pragma mark CommandObjectTargetModulesSearchPathsList
1237ac7ddfbfSEd Maste 
1238435933ddSDimitry Andric class CommandObjectTargetModulesSearchPathsList : public CommandObjectParsed {
1239ac7ddfbfSEd Maste public:
CommandObjectTargetModulesSearchPathsList(CommandInterpreter & interpreter)1240435933ddSDimitry Andric   CommandObjectTargetModulesSearchPathsList(CommandInterpreter &interpreter)
1241435933ddSDimitry Andric       : CommandObjectParsed(interpreter, "target modules search-paths list",
1242435933ddSDimitry Andric                             "List all current image search path substitution "
1243435933ddSDimitry Andric                             "pairs in the current target.",
1244435933ddSDimitry Andric                             "target modules search-paths list") {}
1245ac7ddfbfSEd Maste 
12464bb0738eSEd Maste   ~CommandObjectTargetModulesSearchPathsList() override = default;
1247ac7ddfbfSEd Maste 
1248ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)1249435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
1250ac7ddfbfSEd Maste     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1251435933ddSDimitry Andric     if (target) {
1252435933ddSDimitry Andric       if (command.GetArgumentCount() != 0) {
1253ac7ddfbfSEd Maste         result.AppendError("list takes no arguments\n");
1254ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
1255ac7ddfbfSEd Maste         return result.Succeeded();
1256ac7ddfbfSEd Maste       }
1257ac7ddfbfSEd Maste 
1258ac7ddfbfSEd Maste       target->GetImageSearchPathList().Dump(&result.GetOutputStream());
1259ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusSuccessFinishResult);
1260435933ddSDimitry Andric     } else {
1261ac7ddfbfSEd Maste       result.AppendError("invalid target\n");
1262ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1263ac7ddfbfSEd Maste     }
1264ac7ddfbfSEd Maste     return result.Succeeded();
1265ac7ddfbfSEd Maste   }
1266ac7ddfbfSEd Maste };
1267ac7ddfbfSEd Maste 
1268ac7ddfbfSEd Maste #pragma mark CommandObjectTargetModulesSearchPathsQuery
1269ac7ddfbfSEd Maste 
1270435933ddSDimitry Andric class CommandObjectTargetModulesSearchPathsQuery : public CommandObjectParsed {
1271ac7ddfbfSEd Maste public:
CommandObjectTargetModulesSearchPathsQuery(CommandInterpreter & interpreter)1272435933ddSDimitry Andric   CommandObjectTargetModulesSearchPathsQuery(CommandInterpreter &interpreter)
1273435933ddSDimitry Andric       : CommandObjectParsed(
1274435933ddSDimitry Andric             interpreter, "target modules search-paths query",
1275ac7ddfbfSEd Maste             "Transform a path using the first applicable image search path.",
1276435933ddSDimitry Andric             nullptr) {
1277ac7ddfbfSEd Maste     CommandArgumentEntry arg;
1278ac7ddfbfSEd Maste     CommandArgumentData path_arg;
1279ac7ddfbfSEd Maste 
1280ac7ddfbfSEd Maste     // Define the first (and only) variant of this arg.
1281ac7ddfbfSEd Maste     path_arg.arg_type = eArgTypeDirectoryName;
1282ac7ddfbfSEd Maste     path_arg.arg_repetition = eArgRepeatPlain;
1283ac7ddfbfSEd Maste 
1284435933ddSDimitry Andric     // There is only one variant this argument could be; put it into the
1285435933ddSDimitry Andric     // argument entry.
1286ac7ddfbfSEd Maste     arg.push_back(path_arg);
1287ac7ddfbfSEd Maste 
1288ac7ddfbfSEd Maste     // Push the data for the first argument into the m_arguments vector.
1289ac7ddfbfSEd Maste     m_arguments.push_back(arg);
1290ac7ddfbfSEd Maste   }
1291ac7ddfbfSEd Maste 
12924bb0738eSEd Maste   ~CommandObjectTargetModulesSearchPathsQuery() override = default;
1293ac7ddfbfSEd Maste 
1294ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)1295435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
1296ac7ddfbfSEd Maste     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1297435933ddSDimitry Andric     if (target) {
1298435933ddSDimitry Andric       if (command.GetArgumentCount() != 1) {
1299ac7ddfbfSEd Maste         result.AppendError("query requires one argument\n");
1300ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
1301ac7ddfbfSEd Maste         return result.Succeeded();
1302ac7ddfbfSEd Maste       }
1303ac7ddfbfSEd Maste 
1304ac7ddfbfSEd Maste       ConstString orig(command.GetArgumentAtIndex(0));
1305ac7ddfbfSEd Maste       ConstString transformed;
1306ac7ddfbfSEd Maste       if (target->GetImageSearchPathList().RemapPath(orig, transformed))
1307ac7ddfbfSEd Maste         result.GetOutputStream().Printf("%s\n", transformed.GetCString());
1308ac7ddfbfSEd Maste       else
1309ac7ddfbfSEd Maste         result.GetOutputStream().Printf("%s\n", orig.GetCString());
1310ac7ddfbfSEd Maste 
1311ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusSuccessFinishResult);
1312435933ddSDimitry Andric     } else {
1313ac7ddfbfSEd Maste       result.AppendError("invalid target\n");
1314ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1315ac7ddfbfSEd Maste     }
1316ac7ddfbfSEd Maste     return result.Succeeded();
1317ac7ddfbfSEd Maste   }
1318ac7ddfbfSEd Maste };
1319ac7ddfbfSEd Maste 
1320ac7ddfbfSEd Maste //----------------------------------------------------------------------
1321ac7ddfbfSEd Maste // Static Helper functions
1322ac7ddfbfSEd Maste //----------------------------------------------------------------------
DumpModuleArchitecture(Stream & strm,Module * module,bool full_triple,uint32_t width)1323435933ddSDimitry Andric static void DumpModuleArchitecture(Stream &strm, Module *module,
1324435933ddSDimitry Andric                                    bool full_triple, uint32_t width) {
1325435933ddSDimitry Andric   if (module) {
13269f2f44ceSEd Maste     StreamString arch_strm;
13279f2f44ceSEd Maste 
1328ac7ddfbfSEd Maste     if (full_triple)
13299f2f44ceSEd Maste       module->GetArchitecture().DumpTriple(arch_strm);
1330ac7ddfbfSEd Maste     else
13319f2f44ceSEd Maste       arch_strm.PutCString(module->GetArchitecture().GetArchitectureName());
13329f2f44ceSEd Maste     std::string arch_str = arch_strm.GetString();
13339f2f44ceSEd Maste 
1334ac7ddfbfSEd Maste     if (width)
13359f2f44ceSEd Maste       strm.Printf("%-*s", width, arch_str.c_str());
1336ac7ddfbfSEd Maste     else
1337435933ddSDimitry Andric       strm.PutCString(arch_str);
1338ac7ddfbfSEd Maste   }
1339ac7ddfbfSEd Maste }
1340ac7ddfbfSEd Maste 
DumpModuleUUID(Stream & strm,Module * module)1341435933ddSDimitry Andric static void DumpModuleUUID(Stream &strm, Module *module) {
1342ac7ddfbfSEd Maste   if (module && module->GetUUID().IsValid())
1343ac7ddfbfSEd Maste     module->GetUUID().Dump(&strm);
1344ac7ddfbfSEd Maste   else
1345ac7ddfbfSEd Maste     strm.PutCString("                                    ");
1346ac7ddfbfSEd Maste }
1347ac7ddfbfSEd Maste 
DumpCompileUnitLineTable(CommandInterpreter & interpreter,Stream & strm,Module * module,const FileSpec & file_spec,bool load_addresses)1348435933ddSDimitry Andric static uint32_t DumpCompileUnitLineTable(CommandInterpreter &interpreter,
1349435933ddSDimitry Andric                                          Stream &strm, Module *module,
1350ac7ddfbfSEd Maste                                          const FileSpec &file_spec,
1351435933ddSDimitry Andric                                          bool load_addresses) {
1352ac7ddfbfSEd Maste   uint32_t num_matches = 0;
1353435933ddSDimitry Andric   if (module) {
1354ac7ddfbfSEd Maste     SymbolContextList sc_list;
1355435933ddSDimitry Andric     num_matches = module->ResolveSymbolContextsForFileSpec(
1356435933ddSDimitry Andric         file_spec, 0, false, eSymbolContextCompUnit, sc_list);
1357ac7ddfbfSEd Maste 
1358435933ddSDimitry Andric     for (uint32_t i = 0; i < num_matches; ++i) {
1359ac7ddfbfSEd Maste       SymbolContext sc;
1360435933ddSDimitry Andric       if (sc_list.GetContextAtIndex(i, sc)) {
1361ac7ddfbfSEd Maste         if (i > 0)
1362ac7ddfbfSEd Maste           strm << "\n\n";
1363ac7ddfbfSEd Maste 
1364435933ddSDimitry Andric         strm << "Line table for " << *static_cast<FileSpec *>(sc.comp_unit)
1365435933ddSDimitry Andric              << " in `" << module->GetFileSpec().GetFilename() << "\n";
1366ac7ddfbfSEd Maste         LineTable *line_table = sc.comp_unit->GetLineTable();
1367ac7ddfbfSEd Maste         if (line_table)
1368435933ddSDimitry Andric           line_table->GetDescription(
1369435933ddSDimitry Andric               &strm, interpreter.GetExecutionContext().GetTargetPtr(),
1370ac7ddfbfSEd Maste               lldb::eDescriptionLevelBrief);
1371ac7ddfbfSEd Maste         else
1372ac7ddfbfSEd Maste           strm << "No line table";
1373ac7ddfbfSEd Maste       }
1374ac7ddfbfSEd Maste     }
1375ac7ddfbfSEd Maste   }
1376ac7ddfbfSEd Maste   return num_matches;
1377ac7ddfbfSEd Maste }
1378ac7ddfbfSEd Maste 
DumpFullpath(Stream & strm,const FileSpec * file_spec_ptr,uint32_t width)1379435933ddSDimitry Andric static void DumpFullpath(Stream &strm, const FileSpec *file_spec_ptr,
1380435933ddSDimitry Andric                          uint32_t width) {
1381435933ddSDimitry Andric   if (file_spec_ptr) {
1382435933ddSDimitry Andric     if (width > 0) {
1383ac7ddfbfSEd Maste       std::string fullpath = file_spec_ptr->GetPath();
1384ac7ddfbfSEd Maste       strm.Printf("%-*s", width, fullpath.c_str());
1385ac7ddfbfSEd Maste       return;
1386435933ddSDimitry Andric     } else {
1387ac7ddfbfSEd Maste       file_spec_ptr->Dump(&strm);
1388ac7ddfbfSEd Maste       return;
1389ac7ddfbfSEd Maste     }
1390ac7ddfbfSEd Maste   }
1391ac7ddfbfSEd Maste   // Keep the width spacing correct if things go wrong...
1392ac7ddfbfSEd Maste   if (width > 0)
1393ac7ddfbfSEd Maste     strm.Printf("%-*s", width, "");
1394ac7ddfbfSEd Maste }
1395ac7ddfbfSEd Maste 
DumpDirectory(Stream & strm,const FileSpec * file_spec_ptr,uint32_t width)1396435933ddSDimitry Andric static void DumpDirectory(Stream &strm, const FileSpec *file_spec_ptr,
1397435933ddSDimitry Andric                           uint32_t width) {
1398435933ddSDimitry Andric   if (file_spec_ptr) {
1399ac7ddfbfSEd Maste     if (width > 0)
1400ac7ddfbfSEd Maste       strm.Printf("%-*s", width, file_spec_ptr->GetDirectory().AsCString(""));
1401ac7ddfbfSEd Maste     else
1402ac7ddfbfSEd Maste       file_spec_ptr->GetDirectory().Dump(&strm);
1403ac7ddfbfSEd Maste     return;
1404ac7ddfbfSEd Maste   }
1405ac7ddfbfSEd Maste   // Keep the width spacing correct if things go wrong...
1406ac7ddfbfSEd Maste   if (width > 0)
1407ac7ddfbfSEd Maste     strm.Printf("%-*s", width, "");
1408ac7ddfbfSEd Maste }
1409ac7ddfbfSEd Maste 
DumpBasename(Stream & strm,const FileSpec * file_spec_ptr,uint32_t width)1410435933ddSDimitry Andric static void DumpBasename(Stream &strm, const FileSpec *file_spec_ptr,
1411435933ddSDimitry Andric                          uint32_t width) {
1412435933ddSDimitry Andric   if (file_spec_ptr) {
1413ac7ddfbfSEd Maste     if (width > 0)
1414ac7ddfbfSEd Maste       strm.Printf("%-*s", width, file_spec_ptr->GetFilename().AsCString(""));
1415ac7ddfbfSEd Maste     else
1416ac7ddfbfSEd Maste       file_spec_ptr->GetFilename().Dump(&strm);
1417ac7ddfbfSEd Maste     return;
1418ac7ddfbfSEd Maste   }
1419ac7ddfbfSEd Maste   // Keep the width spacing correct if things go wrong...
1420ac7ddfbfSEd Maste   if (width > 0)
1421ac7ddfbfSEd Maste     strm.Printf("%-*s", width, "");
1422ac7ddfbfSEd Maste }
1423ac7ddfbfSEd Maste 
DumpModuleObjfileHeaders(Stream & strm,ModuleList & module_list)1424435933ddSDimitry Andric static size_t DumpModuleObjfileHeaders(Stream &strm, ModuleList &module_list) {
14254bb0738eSEd Maste   size_t num_dumped = 0;
14264bb0738eSEd Maste   std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex());
14274bb0738eSEd Maste   const size_t num_modules = module_list.GetSize();
1428435933ddSDimitry Andric   if (num_modules > 0) {
1429435933ddSDimitry Andric     strm.Printf("Dumping headers for %" PRIu64 " module(s).\n",
1430435933ddSDimitry Andric                 static_cast<uint64_t>(num_modules));
14314bb0738eSEd Maste     strm.IndentMore();
1432435933ddSDimitry Andric     for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
14334bb0738eSEd Maste       Module *module = module_list.GetModulePointerAtIndexUnlocked(image_idx);
1434435933ddSDimitry Andric       if (module) {
1435435933ddSDimitry Andric         if (num_dumped++ > 0) {
14364bb0738eSEd Maste           strm.EOL();
14374bb0738eSEd Maste           strm.EOL();
14384bb0738eSEd Maste         }
14394bb0738eSEd Maste         ObjectFile *objfile = module->GetObjectFile();
14404ba319b5SDimitry Andric         if (objfile)
14414bb0738eSEd Maste           objfile->Dump(&strm);
14424ba319b5SDimitry Andric         else {
14434ba319b5SDimitry Andric           strm.Format("No object file for module: {0:F}\n",
14444ba319b5SDimitry Andric                       module->GetFileSpec());
14454ba319b5SDimitry Andric         }
14464bb0738eSEd Maste       }
14474bb0738eSEd Maste     }
14484bb0738eSEd Maste     strm.IndentLess();
14494bb0738eSEd Maste   }
14504bb0738eSEd Maste   return num_dumped;
14514bb0738eSEd Maste }
1452ac7ddfbfSEd Maste 
DumpModuleSymtab(CommandInterpreter & interpreter,Stream & strm,Module * module,SortOrder sort_order)1453435933ddSDimitry Andric static void DumpModuleSymtab(CommandInterpreter &interpreter, Stream &strm,
1454435933ddSDimitry Andric                              Module *module, SortOrder sort_order) {
1455435933ddSDimitry Andric   if (module) {
1456ac7ddfbfSEd Maste     SymbolVendor *sym_vendor = module->GetSymbolVendor();
1457435933ddSDimitry Andric     if (sym_vendor) {
1458ac7ddfbfSEd Maste       Symtab *symtab = sym_vendor->GetSymtab();
1459ac7ddfbfSEd Maste       if (symtab)
1460435933ddSDimitry Andric         symtab->Dump(&strm, interpreter.GetExecutionContext().GetTargetPtr(),
1461435933ddSDimitry Andric                      sort_order);
1462ac7ddfbfSEd Maste     }
1463ac7ddfbfSEd Maste   }
1464ac7ddfbfSEd Maste }
1465ac7ddfbfSEd Maste 
DumpModuleSections(CommandInterpreter & interpreter,Stream & strm,Module * module)1466435933ddSDimitry Andric static void DumpModuleSections(CommandInterpreter &interpreter, Stream &strm,
1467435933ddSDimitry Andric                                Module *module) {
1468435933ddSDimitry Andric   if (module) {
1469ac7ddfbfSEd Maste     SectionList *section_list = module->GetSectionList();
1470435933ddSDimitry Andric     if (section_list) {
1471ac7ddfbfSEd Maste       strm.Printf("Sections for '%s' (%s):\n",
1472ac7ddfbfSEd Maste                   module->GetSpecificationDescription().c_str(),
1473ac7ddfbfSEd Maste                   module->GetArchitecture().GetArchitectureName());
1474ac7ddfbfSEd Maste       strm.IndentMore();
1475435933ddSDimitry Andric       section_list->Dump(&strm,
1476435933ddSDimitry Andric                          interpreter.GetExecutionContext().GetTargetPtr(), true,
1477435933ddSDimitry Andric                          UINT32_MAX);
1478ac7ddfbfSEd Maste       strm.IndentLess();
1479ac7ddfbfSEd Maste     }
1480ac7ddfbfSEd Maste   }
1481ac7ddfbfSEd Maste }
1482ac7ddfbfSEd Maste 
DumpModuleSymbolVendor(Stream & strm,Module * module)1483435933ddSDimitry Andric static bool DumpModuleSymbolVendor(Stream &strm, Module *module) {
1484435933ddSDimitry Andric   if (module) {
1485ac7ddfbfSEd Maste     SymbolVendor *symbol_vendor = module->GetSymbolVendor(true);
1486435933ddSDimitry Andric     if (symbol_vendor) {
1487ac7ddfbfSEd Maste       symbol_vendor->Dump(&strm);
1488ac7ddfbfSEd Maste       return true;
1489ac7ddfbfSEd Maste     }
1490ac7ddfbfSEd Maste   }
1491ac7ddfbfSEd Maste   return false;
1492ac7ddfbfSEd Maste }
1493ac7ddfbfSEd Maste 
DumpAddress(ExecutionContextScope * exe_scope,const Address & so_addr,bool verbose,Stream & strm)1494435933ddSDimitry Andric static void DumpAddress(ExecutionContextScope *exe_scope,
1495435933ddSDimitry Andric                         const Address &so_addr, bool verbose, Stream &strm) {
1496ac7ddfbfSEd Maste   strm.IndentMore();
1497ac7ddfbfSEd Maste   strm.Indent("    Address: ");
1498ac7ddfbfSEd Maste   so_addr.Dump(&strm, exe_scope, Address::DumpStyleModuleWithFileAddress);
1499ac7ddfbfSEd Maste   strm.PutCString(" (");
1500ac7ddfbfSEd Maste   so_addr.Dump(&strm, exe_scope, Address::DumpStyleSectionNameOffset);
1501ac7ddfbfSEd Maste   strm.PutCString(")\n");
1502ac7ddfbfSEd Maste   strm.Indent("    Summary: ");
1503ac7ddfbfSEd Maste   const uint32_t save_indent = strm.GetIndentLevel();
1504ac7ddfbfSEd Maste   strm.SetIndentLevel(save_indent + 13);
1505ac7ddfbfSEd Maste   so_addr.Dump(&strm, exe_scope, Address::DumpStyleResolvedDescription);
1506ac7ddfbfSEd Maste   strm.SetIndentLevel(save_indent);
1507ac7ddfbfSEd Maste   // Print out detailed address information when verbose is enabled
1508435933ddSDimitry Andric   if (verbose) {
1509ac7ddfbfSEd Maste     strm.EOL();
1510ac7ddfbfSEd Maste     so_addr.Dump(&strm, exe_scope, Address::DumpStyleDetailedSymbolContext);
1511ac7ddfbfSEd Maste   }
1512ac7ddfbfSEd Maste   strm.IndentLess();
1513ac7ddfbfSEd Maste }
1514ac7ddfbfSEd Maste 
LookupAddressInModule(CommandInterpreter & interpreter,Stream & strm,Module * module,uint32_t resolve_mask,lldb::addr_t raw_addr,lldb::addr_t offset,bool verbose)1515435933ddSDimitry Andric static bool LookupAddressInModule(CommandInterpreter &interpreter, Stream &strm,
1516435933ddSDimitry Andric                                   Module *module, uint32_t resolve_mask,
1517435933ddSDimitry Andric                                   lldb::addr_t raw_addr, lldb::addr_t offset,
1518435933ddSDimitry Andric                                   bool verbose) {
1519435933ddSDimitry Andric   if (module) {
1520ac7ddfbfSEd Maste     lldb::addr_t addr = raw_addr - offset;
1521ac7ddfbfSEd Maste     Address so_addr;
1522ac7ddfbfSEd Maste     SymbolContext sc;
1523ac7ddfbfSEd Maste     Target *target = interpreter.GetExecutionContext().GetTargetPtr();
1524435933ddSDimitry Andric     if (target && !target->GetSectionLoadList().IsEmpty()) {
1525ac7ddfbfSEd Maste       if (!target->GetSectionLoadList().ResolveLoadAddress(addr, so_addr))
1526ac7ddfbfSEd Maste         return false;
1527ac7ddfbfSEd Maste       else if (so_addr.GetModule().get() != module)
1528ac7ddfbfSEd Maste         return false;
1529435933ddSDimitry Andric     } else {
1530ac7ddfbfSEd Maste       if (!module->ResolveFileAddress(addr, so_addr))
1531ac7ddfbfSEd Maste         return false;
1532ac7ddfbfSEd Maste     }
1533ac7ddfbfSEd Maste 
1534435933ddSDimitry Andric     ExecutionContextScope *exe_scope =
1535435933ddSDimitry Andric         interpreter.GetExecutionContext().GetBestExecutionContextScope();
1536ac7ddfbfSEd Maste     DumpAddress(exe_scope, so_addr, verbose, strm);
1537ac7ddfbfSEd Maste     //        strm.IndentMore();
1538ac7ddfbfSEd Maste     //        strm.Indent ("    Address: ");
1539435933ddSDimitry Andric     //        so_addr.Dump (&strm, exe_scope,
1540435933ddSDimitry Andric     //        Address::DumpStyleModuleWithFileAddress);
1541ac7ddfbfSEd Maste     //        strm.PutCString (" (");
1542435933ddSDimitry Andric     //        so_addr.Dump (&strm, exe_scope,
1543435933ddSDimitry Andric     //        Address::DumpStyleSectionNameOffset);
1544ac7ddfbfSEd Maste     //        strm.PutCString (")\n");
1545ac7ddfbfSEd Maste     //        strm.Indent ("    Summary: ");
1546ac7ddfbfSEd Maste     //        const uint32_t save_indent = strm.GetIndentLevel ();
1547ac7ddfbfSEd Maste     //        strm.SetIndentLevel (save_indent + 13);
1548435933ddSDimitry Andric     //        so_addr.Dump (&strm, exe_scope,
1549435933ddSDimitry Andric     //        Address::DumpStyleResolvedDescription);
1550ac7ddfbfSEd Maste     //        strm.SetIndentLevel (save_indent);
1551ac7ddfbfSEd Maste     //        // Print out detailed address information when verbose is enabled
1552ac7ddfbfSEd Maste     //        if (verbose)
1553ac7ddfbfSEd Maste     //        {
1554ac7ddfbfSEd Maste     //            strm.EOL();
1555435933ddSDimitry Andric     //            so_addr.Dump (&strm, exe_scope,
1556435933ddSDimitry Andric     //            Address::DumpStyleDetailedSymbolContext);
1557ac7ddfbfSEd Maste     //        }
1558ac7ddfbfSEd Maste     //        strm.IndentLess();
1559ac7ddfbfSEd Maste     return true;
1560ac7ddfbfSEd Maste   }
1561ac7ddfbfSEd Maste 
1562ac7ddfbfSEd Maste   return false;
1563ac7ddfbfSEd Maste }
1564ac7ddfbfSEd Maste 
LookupSymbolInModule(CommandInterpreter & interpreter,Stream & strm,Module * module,const char * name,bool name_is_regex,bool verbose)1565435933ddSDimitry Andric static uint32_t LookupSymbolInModule(CommandInterpreter &interpreter,
1566435933ddSDimitry Andric                                      Stream &strm, Module *module,
1567435933ddSDimitry Andric                                      const char *name, bool name_is_regex,
1568435933ddSDimitry Andric                                      bool verbose) {
1569435933ddSDimitry Andric   if (module) {
1570ac7ddfbfSEd Maste     SymbolContext sc;
1571ac7ddfbfSEd Maste 
1572ac7ddfbfSEd Maste     SymbolVendor *sym_vendor = module->GetSymbolVendor();
1573435933ddSDimitry Andric     if (sym_vendor) {
1574ac7ddfbfSEd Maste       Symtab *symtab = sym_vendor->GetSymtab();
1575435933ddSDimitry Andric       if (symtab) {
1576ac7ddfbfSEd Maste         std::vector<uint32_t> match_indexes;
1577ac7ddfbfSEd Maste         ConstString symbol_name(name);
1578ac7ddfbfSEd Maste         uint32_t num_matches = 0;
1579435933ddSDimitry Andric         if (name_is_regex) {
1580435933ddSDimitry Andric           RegularExpression name_regexp(symbol_name.GetStringRef());
1581435933ddSDimitry Andric           num_matches = symtab->AppendSymbolIndexesMatchingRegExAndType(
1582435933ddSDimitry Andric               name_regexp, eSymbolTypeAny, match_indexes);
1583435933ddSDimitry Andric         } else {
1584435933ddSDimitry Andric           num_matches =
1585435933ddSDimitry Andric               symtab->AppendSymbolIndexesWithName(symbol_name, match_indexes);
1586ac7ddfbfSEd Maste         }
1587ac7ddfbfSEd Maste 
1588435933ddSDimitry Andric         if (num_matches > 0) {
1589ac7ddfbfSEd Maste           strm.Indent();
1590ac7ddfbfSEd Maste           strm.Printf("%u symbols match %s'%s' in ", num_matches,
1591ac7ddfbfSEd Maste                       name_is_regex ? "the regular expression " : "", name);
1592ac7ddfbfSEd Maste           DumpFullpath(strm, &module->GetFileSpec(), 0);
1593ac7ddfbfSEd Maste           strm.PutCString(":\n");
1594ac7ddfbfSEd Maste           strm.IndentMore();
1595435933ddSDimitry Andric           for (uint32_t i = 0; i < num_matches; ++i) {
1596ac7ddfbfSEd Maste             Symbol *symbol = symtab->SymbolAtIndex(match_indexes[i]);
1597435933ddSDimitry Andric             if (symbol && symbol->ValueIsAddress()) {
1598435933ddSDimitry Andric               DumpAddress(interpreter.GetExecutionContext()
1599435933ddSDimitry Andric                               .GetBestExecutionContextScope(),
1600435933ddSDimitry Andric                           symbol->GetAddressRef(), verbose, strm);
16011c3bbb01SEd Maste             }
1602ac7ddfbfSEd Maste           }
1603ac7ddfbfSEd Maste           strm.IndentLess();
1604ac7ddfbfSEd Maste           return num_matches;
1605ac7ddfbfSEd Maste         }
1606ac7ddfbfSEd Maste       }
1607ac7ddfbfSEd Maste     }
1608ac7ddfbfSEd Maste   }
1609ac7ddfbfSEd Maste   return 0;
1610ac7ddfbfSEd Maste }
1611ac7ddfbfSEd Maste 
DumpSymbolContextList(ExecutionContextScope * exe_scope,Stream & strm,SymbolContextList & sc_list,bool verbose)1612435933ddSDimitry Andric static void DumpSymbolContextList(ExecutionContextScope *exe_scope,
1613435933ddSDimitry Andric                                   Stream &strm, SymbolContextList &sc_list,
1614435933ddSDimitry Andric                                   bool verbose) {
1615ac7ddfbfSEd Maste   strm.IndentMore();
16164bb0738eSEd Maste 
1617ac7ddfbfSEd Maste   const uint32_t num_matches = sc_list.GetSize();
1618ac7ddfbfSEd Maste 
1619435933ddSDimitry Andric   for (uint32_t i = 0; i < num_matches; ++i) {
1620ac7ddfbfSEd Maste     SymbolContext sc;
1621435933ddSDimitry Andric     if (sc_list.GetContextAtIndex(i, sc)) {
1622ac7ddfbfSEd Maste       AddressRange range;
1623ac7ddfbfSEd Maste 
1624435933ddSDimitry Andric       sc.GetAddressRange(eSymbolContextEverything, 0, true, range);
1625ac7ddfbfSEd Maste 
1626ac7ddfbfSEd Maste       DumpAddress(exe_scope, range.GetBaseAddress(), verbose, strm);
1627ac7ddfbfSEd Maste     }
1628ac7ddfbfSEd Maste   }
1629ac7ddfbfSEd Maste   strm.IndentLess();
1630ac7ddfbfSEd Maste }
1631ac7ddfbfSEd Maste 
LookupFunctionInModule(CommandInterpreter & interpreter,Stream & strm,Module * module,const char * name,bool name_is_regex,bool include_inlines,bool include_symbols,bool verbose)1632435933ddSDimitry Andric static size_t LookupFunctionInModule(CommandInterpreter &interpreter,
1633435933ddSDimitry Andric                                      Stream &strm, Module *module,
1634435933ddSDimitry Andric                                      const char *name, bool name_is_regex,
1635435933ddSDimitry Andric                                      bool include_inlines, bool include_symbols,
1636435933ddSDimitry Andric                                      bool verbose) {
1637435933ddSDimitry Andric   if (module && name && name[0]) {
1638ac7ddfbfSEd Maste     SymbolContextList sc_list;
1639ac7ddfbfSEd Maste     const bool append = true;
1640ac7ddfbfSEd Maste     size_t num_matches = 0;
1641435933ddSDimitry Andric     if (name_is_regex) {
1642435933ddSDimitry Andric       RegularExpression function_name_regex((llvm::StringRef(name)));
1643435933ddSDimitry Andric       num_matches = module->FindFunctions(function_name_regex, include_symbols,
1644435933ddSDimitry Andric                                           include_inlines, append, sc_list);
1645435933ddSDimitry Andric     } else {
1646ac7ddfbfSEd Maste       ConstString function_name(name);
1647435933ddSDimitry Andric       num_matches = module->FindFunctions(
1648435933ddSDimitry Andric           function_name, nullptr, eFunctionNameTypeAuto, include_symbols,
1649435933ddSDimitry Andric           include_inlines, append, sc_list);
1650ac7ddfbfSEd Maste     }
1651ac7ddfbfSEd Maste 
1652435933ddSDimitry Andric     if (num_matches) {
1653ac7ddfbfSEd Maste       strm.Indent();
1654435933ddSDimitry Andric       strm.Printf("%" PRIu64 " match%s found in ", (uint64_t)num_matches,
1655435933ddSDimitry Andric                   num_matches > 1 ? "es" : "");
1656ac7ddfbfSEd Maste       DumpFullpath(strm, &module->GetFileSpec(), 0);
1657ac7ddfbfSEd Maste       strm.PutCString(":\n");
1658435933ddSDimitry Andric       DumpSymbolContextList(
1659435933ddSDimitry Andric           interpreter.GetExecutionContext().GetBestExecutionContextScope(),
1660435933ddSDimitry Andric           strm, sc_list, verbose);
1661ac7ddfbfSEd Maste     }
1662ac7ddfbfSEd Maste     return num_matches;
1663ac7ddfbfSEd Maste   }
1664ac7ddfbfSEd Maste   return 0;
1665ac7ddfbfSEd Maste }
1666ac7ddfbfSEd Maste 
LookupTypeInModule(CommandInterpreter & interpreter,Stream & strm,Module * module,const char * name_cstr,bool name_is_regex)1667435933ddSDimitry Andric static size_t LookupTypeInModule(CommandInterpreter &interpreter, Stream &strm,
1668435933ddSDimitry Andric                                  Module *module, const char *name_cstr,
1669435933ddSDimitry Andric                                  bool name_is_regex) {
1670435933ddSDimitry Andric   if (module && name_cstr && name_cstr[0]) {
1671ac7ddfbfSEd Maste     TypeList type_list;
1672ac7ddfbfSEd Maste     const uint32_t max_num_matches = UINT32_MAX;
1673ac7ddfbfSEd Maste     size_t num_matches = 0;
1674ac7ddfbfSEd Maste     bool name_is_fully_qualified = false;
1675ac7ddfbfSEd Maste 
1676ac7ddfbfSEd Maste     ConstString name(name_cstr);
16774bb0738eSEd Maste     llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files;
1678435933ddSDimitry Andric     num_matches =
1679*b5893f02SDimitry Andric         module->FindTypes(name, name_is_fully_qualified, max_num_matches,
1680435933ddSDimitry Andric                           searched_symbol_files, type_list);
1681ac7ddfbfSEd Maste 
1682435933ddSDimitry Andric     if (num_matches) {
1683ac7ddfbfSEd Maste       strm.Indent();
1684435933ddSDimitry Andric       strm.Printf("%" PRIu64 " match%s found in ", (uint64_t)num_matches,
1685435933ddSDimitry Andric                   num_matches > 1 ? "es" : "");
1686ac7ddfbfSEd Maste       DumpFullpath(strm, &module->GetFileSpec(), 0);
1687ac7ddfbfSEd Maste       strm.PutCString(":\n");
1688435933ddSDimitry Andric       for (TypeSP type_sp : type_list.Types()) {
1689435933ddSDimitry Andric         if (type_sp) {
16904ba319b5SDimitry Andric           // Resolve the clang type so that any forward references to types
16914ba319b5SDimitry Andric           // that haven't yet been parsed will get parsed.
16929f2f44ceSEd Maste           type_sp->GetFullCompilerType();
1693ac7ddfbfSEd Maste           type_sp->GetDescription(&strm, eDescriptionLevelFull, true);
1694ac7ddfbfSEd Maste           // Print all typedef chains
1695ac7ddfbfSEd Maste           TypeSP typedef_type_sp(type_sp);
1696ac7ddfbfSEd Maste           TypeSP typedefed_type_sp(typedef_type_sp->GetTypedefType());
1697435933ddSDimitry Andric           while (typedefed_type_sp) {
1698ac7ddfbfSEd Maste             strm.EOL();
1699435933ddSDimitry Andric             strm.Printf("     typedef '%s': ",
1700435933ddSDimitry Andric                         typedef_type_sp->GetName().GetCString());
17019f2f44ceSEd Maste             typedefed_type_sp->GetFullCompilerType();
1702435933ddSDimitry Andric             typedefed_type_sp->GetDescription(&strm, eDescriptionLevelFull,
1703435933ddSDimitry Andric                                               true);
1704ac7ddfbfSEd Maste             typedef_type_sp = typedefed_type_sp;
1705ac7ddfbfSEd Maste             typedefed_type_sp = typedef_type_sp->GetTypedefType();
1706ac7ddfbfSEd Maste           }
1707ac7ddfbfSEd Maste         }
1708ac7ddfbfSEd Maste         strm.EOL();
1709ac7ddfbfSEd Maste       }
1710ac7ddfbfSEd Maste     }
1711ac7ddfbfSEd Maste     return num_matches;
1712ac7ddfbfSEd Maste   }
1713ac7ddfbfSEd Maste   return 0;
1714ac7ddfbfSEd Maste }
1715ac7ddfbfSEd Maste 
LookupTypeHere(CommandInterpreter & interpreter,Stream & strm,Module & module,const char * name_cstr,bool name_is_regex)1716435933ddSDimitry Andric static size_t LookupTypeHere(CommandInterpreter &interpreter, Stream &strm,
1717*b5893f02SDimitry Andric                              Module &module, const char *name_cstr,
1718*b5893f02SDimitry Andric                              bool name_is_regex) {
1719ac7ddfbfSEd Maste   TypeList type_list;
1720ac7ddfbfSEd Maste   const uint32_t max_num_matches = UINT32_MAX;
1721ac7ddfbfSEd Maste   size_t num_matches = 1;
1722ac7ddfbfSEd Maste   bool name_is_fully_qualified = false;
1723ac7ddfbfSEd Maste 
1724ac7ddfbfSEd Maste   ConstString name(name_cstr);
17254bb0738eSEd Maste   llvm::DenseSet<SymbolFile *> searched_symbol_files;
1726*b5893f02SDimitry Andric   num_matches = module.FindTypes(name, name_is_fully_qualified, max_num_matches,
1727435933ddSDimitry Andric                                  searched_symbol_files, type_list);
1728ac7ddfbfSEd Maste 
1729435933ddSDimitry Andric   if (num_matches) {
1730ac7ddfbfSEd Maste     strm.Indent();
1731ac7ddfbfSEd Maste     strm.PutCString("Best match found in ");
1732*b5893f02SDimitry Andric     DumpFullpath(strm, &module.GetFileSpec(), 0);
1733ac7ddfbfSEd Maste     strm.PutCString(":\n");
1734ac7ddfbfSEd Maste 
1735ac7ddfbfSEd Maste     TypeSP type_sp(type_list.GetTypeAtIndex(0));
1736435933ddSDimitry Andric     if (type_sp) {
17374ba319b5SDimitry Andric       // Resolve the clang type so that any forward references to types that
17384ba319b5SDimitry Andric       // haven't yet been parsed will get parsed.
17399f2f44ceSEd Maste       type_sp->GetFullCompilerType();
1740ac7ddfbfSEd Maste       type_sp->GetDescription(&strm, eDescriptionLevelFull, true);
1741ac7ddfbfSEd Maste       // Print all typedef chains
1742ac7ddfbfSEd Maste       TypeSP typedef_type_sp(type_sp);
1743ac7ddfbfSEd Maste       TypeSP typedefed_type_sp(typedef_type_sp->GetTypedefType());
1744435933ddSDimitry Andric       while (typedefed_type_sp) {
1745ac7ddfbfSEd Maste         strm.EOL();
1746435933ddSDimitry Andric         strm.Printf("     typedef '%s': ",
1747435933ddSDimitry Andric                     typedef_type_sp->GetName().GetCString());
17489f2f44ceSEd Maste         typedefed_type_sp->GetFullCompilerType();
1749ac7ddfbfSEd Maste         typedefed_type_sp->GetDescription(&strm, eDescriptionLevelFull, true);
1750ac7ddfbfSEd Maste         typedef_type_sp = typedefed_type_sp;
1751ac7ddfbfSEd Maste         typedefed_type_sp = typedef_type_sp->GetTypedefType();
1752ac7ddfbfSEd Maste       }
1753ac7ddfbfSEd Maste     }
1754ac7ddfbfSEd Maste     strm.EOL();
1755ac7ddfbfSEd Maste   }
1756ac7ddfbfSEd Maste   return num_matches;
1757ac7ddfbfSEd Maste }
1758ac7ddfbfSEd Maste 
LookupFileAndLineInModule(CommandInterpreter & interpreter,Stream & strm,Module * module,const FileSpec & file_spec,uint32_t line,bool check_inlines,bool verbose)1759435933ddSDimitry Andric static uint32_t LookupFileAndLineInModule(CommandInterpreter &interpreter,
1760435933ddSDimitry Andric                                           Stream &strm, Module *module,
1761ac7ddfbfSEd Maste                                           const FileSpec &file_spec,
1762435933ddSDimitry Andric                                           uint32_t line, bool check_inlines,
1763435933ddSDimitry Andric                                           bool verbose) {
1764435933ddSDimitry Andric   if (module && file_spec) {
1765ac7ddfbfSEd Maste     SymbolContextList sc_list;
1766435933ddSDimitry Andric     const uint32_t num_matches = module->ResolveSymbolContextsForFileSpec(
1767435933ddSDimitry Andric         file_spec, line, check_inlines, eSymbolContextEverything, sc_list);
1768435933ddSDimitry Andric     if (num_matches > 0) {
1769ac7ddfbfSEd Maste       strm.Indent();
1770435933ddSDimitry Andric       strm.Printf("%u match%s found in ", num_matches,
1771435933ddSDimitry Andric                   num_matches > 1 ? "es" : "");
1772ac7ddfbfSEd Maste       strm << file_spec;
1773ac7ddfbfSEd Maste       if (line > 0)
1774ac7ddfbfSEd Maste         strm.Printf(":%u", line);
1775ac7ddfbfSEd Maste       strm << " in ";
1776ac7ddfbfSEd Maste       DumpFullpath(strm, &module->GetFileSpec(), 0);
1777ac7ddfbfSEd Maste       strm.PutCString(":\n");
1778435933ddSDimitry Andric       DumpSymbolContextList(
1779435933ddSDimitry Andric           interpreter.GetExecutionContext().GetBestExecutionContextScope(),
1780435933ddSDimitry Andric           strm, sc_list, verbose);
1781ac7ddfbfSEd Maste       return num_matches;
1782ac7ddfbfSEd Maste     }
1783ac7ddfbfSEd Maste   }
1784ac7ddfbfSEd Maste   return 0;
1785ac7ddfbfSEd Maste }
1786ac7ddfbfSEd Maste 
FindModulesByName(Target * target,const char * module_name,ModuleList & module_list,bool check_global_list)1787435933ddSDimitry Andric static size_t FindModulesByName(Target *target, const char *module_name,
1788ac7ddfbfSEd Maste                                 ModuleList &module_list,
1789435933ddSDimitry Andric                                 bool check_global_list) {
1790*b5893f02SDimitry Andric   FileSpec module_file_spec(module_name);
1791ac7ddfbfSEd Maste   ModuleSpec module_spec(module_file_spec);
1792ac7ddfbfSEd Maste 
1793ac7ddfbfSEd Maste   const size_t initial_size = module_list.GetSize();
1794ac7ddfbfSEd Maste 
1795435933ddSDimitry Andric   if (check_global_list) {
1796ac7ddfbfSEd Maste     // Check the global list
1797435933ddSDimitry Andric     std::lock_guard<std::recursive_mutex> guard(
1798435933ddSDimitry Andric         Module::GetAllocationModuleCollectionMutex());
1799ac7ddfbfSEd Maste     const size_t num_modules = Module::GetNumberAllocatedModules();
1800ac7ddfbfSEd Maste     ModuleSP module_sp;
1801435933ddSDimitry Andric     for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
1802ac7ddfbfSEd Maste       Module *module = Module::GetAllocatedModuleAtIndex(image_idx);
1803ac7ddfbfSEd Maste 
1804435933ddSDimitry Andric       if (module) {
1805435933ddSDimitry Andric         if (module->MatchesModuleSpec(module_spec)) {
1806ac7ddfbfSEd Maste           module_sp = module->shared_from_this();
1807ac7ddfbfSEd Maste           module_list.AppendIfNeeded(module_sp);
1808ac7ddfbfSEd Maste         }
1809ac7ddfbfSEd Maste       }
1810ac7ddfbfSEd Maste     }
1811435933ddSDimitry Andric   } else {
1812435933ddSDimitry Andric     if (target) {
1813435933ddSDimitry Andric       const size_t num_matches =
1814435933ddSDimitry Andric           target->GetImages().FindModules(module_spec, module_list);
1815ac7ddfbfSEd Maste 
18164ba319b5SDimitry Andric       // Not found in our module list for our target, check the main shared
18174ba319b5SDimitry Andric       // module list in case it is a extra file used somewhere else
1818435933ddSDimitry Andric       if (num_matches == 0) {
1819ac7ddfbfSEd Maste         module_spec.GetArchitecture() = target->GetArchitecture();
1820ac7ddfbfSEd Maste         ModuleList::FindSharedModules(module_spec, module_list);
1821ac7ddfbfSEd Maste       }
1822435933ddSDimitry Andric     } else {
1823ac7ddfbfSEd Maste       ModuleList::FindSharedModules(module_spec, module_list);
1824ac7ddfbfSEd Maste     }
1825ac7ddfbfSEd Maste   }
1826ac7ddfbfSEd Maste 
1827ac7ddfbfSEd Maste   return module_list.GetSize() - initial_size;
1828ac7ddfbfSEd Maste }
1829ac7ddfbfSEd Maste 
1830ac7ddfbfSEd Maste #pragma mark CommandObjectTargetModulesModuleAutoComplete
1831ac7ddfbfSEd Maste 
1832ac7ddfbfSEd Maste //----------------------------------------------------------------------
1833ac7ddfbfSEd Maste // A base command object class that can auto complete with module file
1834ac7ddfbfSEd Maste // paths
1835ac7ddfbfSEd Maste //----------------------------------------------------------------------
1836ac7ddfbfSEd Maste 
1837435933ddSDimitry Andric class CommandObjectTargetModulesModuleAutoComplete
1838435933ddSDimitry Andric     : public CommandObjectParsed {
1839ac7ddfbfSEd Maste public:
CommandObjectTargetModulesModuleAutoComplete(CommandInterpreter & interpreter,const char * name,const char * help,const char * syntax)1840ac7ddfbfSEd Maste   CommandObjectTargetModulesModuleAutoComplete(CommandInterpreter &interpreter,
1841ac7ddfbfSEd Maste                                                const char *name,
1842ac7ddfbfSEd Maste                                                const char *help,
1843435933ddSDimitry Andric                                                const char *syntax)
1844435933ddSDimitry Andric       : CommandObjectParsed(interpreter, name, help, syntax) {
1845ac7ddfbfSEd Maste     CommandArgumentEntry arg;
1846ac7ddfbfSEd Maste     CommandArgumentData file_arg;
1847ac7ddfbfSEd Maste 
1848ac7ddfbfSEd Maste     // Define the first (and only) variant of this arg.
1849ac7ddfbfSEd Maste     file_arg.arg_type = eArgTypeFilename;
1850ac7ddfbfSEd Maste     file_arg.arg_repetition = eArgRepeatStar;
1851ac7ddfbfSEd Maste 
1852435933ddSDimitry Andric     // There is only one variant this argument could be; put it into the
1853435933ddSDimitry Andric     // argument entry.
1854ac7ddfbfSEd Maste     arg.push_back(file_arg);
1855ac7ddfbfSEd Maste 
1856ac7ddfbfSEd Maste     // Push the data for the first argument into the m_arguments vector.
1857ac7ddfbfSEd Maste     m_arguments.push_back(arg);
1858ac7ddfbfSEd Maste   }
1859ac7ddfbfSEd Maste 
18604bb0738eSEd Maste   ~CommandObjectTargetModulesModuleAutoComplete() override = default;
1861ac7ddfbfSEd Maste 
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)18624ba319b5SDimitry Andric   int HandleArgumentCompletion(
18634ba319b5SDimitry Andric       CompletionRequest &request,
18644ba319b5SDimitry Andric       OptionElementVector &opt_element_vector) override {
1865435933ddSDimitry Andric     CommandCompletions::InvokeCommonCompletionCallbacks(
18664ba319b5SDimitry Andric         GetCommandInterpreter(), CommandCompletions::eModuleCompletion, request,
18674ba319b5SDimitry Andric         nullptr);
18684ba319b5SDimitry Andric     return request.GetNumberOfMatches();
1869ac7ddfbfSEd Maste   }
1870ac7ddfbfSEd Maste };
1871ac7ddfbfSEd Maste 
1872ac7ddfbfSEd Maste #pragma mark CommandObjectTargetModulesSourceFileAutoComplete
1873ac7ddfbfSEd Maste 
1874ac7ddfbfSEd Maste //----------------------------------------------------------------------
1875ac7ddfbfSEd Maste // A base command object class that can auto complete with module source
1876ac7ddfbfSEd Maste // file paths
1877ac7ddfbfSEd Maste //----------------------------------------------------------------------
1878ac7ddfbfSEd Maste 
1879435933ddSDimitry Andric class CommandObjectTargetModulesSourceFileAutoComplete
1880435933ddSDimitry Andric     : public CommandObjectParsed {
1881ac7ddfbfSEd Maste public:
CommandObjectTargetModulesSourceFileAutoComplete(CommandInterpreter & interpreter,const char * name,const char * help,const char * syntax,uint32_t flags)1882435933ddSDimitry Andric   CommandObjectTargetModulesSourceFileAutoComplete(
1883435933ddSDimitry Andric       CommandInterpreter &interpreter, const char *name, const char *help,
1884435933ddSDimitry Andric       const char *syntax, uint32_t flags)
1885435933ddSDimitry Andric       : CommandObjectParsed(interpreter, name, help, syntax, flags) {
1886ac7ddfbfSEd Maste     CommandArgumentEntry arg;
1887ac7ddfbfSEd Maste     CommandArgumentData source_file_arg;
1888ac7ddfbfSEd Maste 
1889ac7ddfbfSEd Maste     // Define the first (and only) variant of this arg.
1890ac7ddfbfSEd Maste     source_file_arg.arg_type = eArgTypeSourceFile;
1891ac7ddfbfSEd Maste     source_file_arg.arg_repetition = eArgRepeatPlus;
1892ac7ddfbfSEd Maste 
1893435933ddSDimitry Andric     // There is only one variant this argument could be; put it into the
1894435933ddSDimitry Andric     // argument entry.
1895ac7ddfbfSEd Maste     arg.push_back(source_file_arg);
1896ac7ddfbfSEd Maste 
1897ac7ddfbfSEd Maste     // Push the data for the first argument into the m_arguments vector.
1898ac7ddfbfSEd Maste     m_arguments.push_back(arg);
1899ac7ddfbfSEd Maste   }
1900ac7ddfbfSEd Maste 
19014bb0738eSEd Maste   ~CommandObjectTargetModulesSourceFileAutoComplete() override = default;
1902ac7ddfbfSEd Maste 
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)19034ba319b5SDimitry Andric   int HandleArgumentCompletion(
19044ba319b5SDimitry Andric       CompletionRequest &request,
19054ba319b5SDimitry Andric       OptionElementVector &opt_element_vector) override {
1906435933ddSDimitry Andric     CommandCompletions::InvokeCommonCompletionCallbacks(
1907435933ddSDimitry Andric         GetCommandInterpreter(), CommandCompletions::eSourceFileCompletion,
19084ba319b5SDimitry Andric         request, nullptr);
19094ba319b5SDimitry Andric     return request.GetNumberOfMatches();
1910ac7ddfbfSEd Maste   }
1911ac7ddfbfSEd Maste };
1912ac7ddfbfSEd Maste 
19134bb0738eSEd Maste #pragma mark CommandObjectTargetModulesDumpObjfile
19144bb0738eSEd Maste 
1915435933ddSDimitry Andric class CommandObjectTargetModulesDumpObjfile
1916435933ddSDimitry Andric     : public CommandObjectTargetModulesModuleAutoComplete {
19174bb0738eSEd Maste public:
CommandObjectTargetModulesDumpObjfile(CommandInterpreter & interpreter)19184bb0738eSEd Maste   CommandObjectTargetModulesDumpObjfile(CommandInterpreter &interpreter)
1919435933ddSDimitry Andric       : CommandObjectTargetModulesModuleAutoComplete(
1920435933ddSDimitry Andric             interpreter, "target modules dump objfile",
19214bb0738eSEd Maste             "Dump the object file headers from one or more target modules.",
1922435933ddSDimitry Andric             nullptr) {}
19234bb0738eSEd Maste 
19244bb0738eSEd Maste   ~CommandObjectTargetModulesDumpObjfile() override = default;
19254bb0738eSEd Maste 
19264bb0738eSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)1927435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
19284bb0738eSEd Maste     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1929435933ddSDimitry Andric     if (target == nullptr) {
1930435933ddSDimitry Andric       result.AppendError("invalid target, create a debug target using the "
1931435933ddSDimitry Andric                          "'target create' command");
19324bb0738eSEd Maste       result.SetStatus(eReturnStatusFailed);
19334bb0738eSEd Maste       return false;
19344bb0738eSEd Maste     }
19354bb0738eSEd Maste 
19364bb0738eSEd Maste     uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
19374bb0738eSEd Maste     result.GetOutputStream().SetAddressByteSize(addr_byte_size);
19384bb0738eSEd Maste     result.GetErrorStream().SetAddressByteSize(addr_byte_size);
19394bb0738eSEd Maste 
19404bb0738eSEd Maste     size_t num_dumped = 0;
1941435933ddSDimitry Andric     if (command.GetArgumentCount() == 0) {
19424bb0738eSEd Maste       // Dump all headers for all modules images
1943435933ddSDimitry Andric       num_dumped = DumpModuleObjfileHeaders(result.GetOutputStream(),
1944435933ddSDimitry Andric                                             target->GetImages());
1945435933ddSDimitry Andric       if (num_dumped == 0) {
19464bb0738eSEd Maste         result.AppendError("the target has no associated executable images");
19474bb0738eSEd Maste         result.SetStatus(eReturnStatusFailed);
19484bb0738eSEd Maste       }
1949435933ddSDimitry Andric     } else {
19504bb0738eSEd Maste       // Find the modules that match the basename or full path.
19514bb0738eSEd Maste       ModuleList module_list;
19524bb0738eSEd Maste       const char *arg_cstr;
1953435933ddSDimitry Andric       for (int arg_idx = 0;
1954435933ddSDimitry Andric            (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
1955435933ddSDimitry Andric            ++arg_idx) {
1956435933ddSDimitry Andric         size_t num_matched =
1957435933ddSDimitry Andric             FindModulesByName(target, arg_cstr, module_list, true);
1958435933ddSDimitry Andric         if (num_matched == 0) {
1959435933ddSDimitry Andric           result.AppendWarningWithFormat(
1960435933ddSDimitry Andric               "Unable to find an image that matches '%s'.\n", arg_cstr);
19614bb0738eSEd Maste         }
19624bb0738eSEd Maste       }
19634bb0738eSEd Maste       // Dump all the modules we found.
1964435933ddSDimitry Andric       num_dumped =
1965435933ddSDimitry Andric           DumpModuleObjfileHeaders(result.GetOutputStream(), module_list);
19664bb0738eSEd Maste     }
19674bb0738eSEd Maste 
1968435933ddSDimitry Andric     if (num_dumped > 0) {
19694bb0738eSEd Maste       result.SetStatus(eReturnStatusSuccessFinishResult);
1970435933ddSDimitry Andric     } else {
19714bb0738eSEd Maste       result.AppendError("no matching executable images found");
19724bb0738eSEd Maste       result.SetStatus(eReturnStatusFailed);
19734bb0738eSEd Maste     }
19744bb0738eSEd Maste     return result.Succeeded();
19754bb0738eSEd Maste   }
19764bb0738eSEd Maste };
1977ac7ddfbfSEd Maste 
1978ac7ddfbfSEd Maste #pragma mark CommandObjectTargetModulesDumpSymtab
1979ac7ddfbfSEd Maste 
1980*b5893f02SDimitry Andric static constexpr OptionEnumValueElement g_sort_option_enumeration[] = {
1981435933ddSDimitry Andric     {eSortOrderNone, "none",
1982435933ddSDimitry Andric      "No sorting, use the original symbol table order."},
1983435933ddSDimitry Andric     {eSortOrderByAddress, "address", "Sort output by symbol address."},
1984*b5893f02SDimitry Andric     {eSortOrderByName, "name", "Sort output by symbol name."} };
1985435933ddSDimitry Andric 
1986*b5893f02SDimitry Andric static constexpr OptionDefinition g_target_modules_dump_symtab_options[] = {
1987435933ddSDimitry Andric     // clang-format off
1988*b5893f02SDimitry Andric   { LLDB_OPT_SET_1, false, "sort", 's', OptionParser::eRequiredArgument, nullptr, OptionEnumValues(g_sort_option_enumeration), 0, eArgTypeSortOrder, "Supply a sort order when dumping the symbol table." }
1989435933ddSDimitry Andric     // clang-format on
1990435933ddSDimitry Andric };
1991435933ddSDimitry Andric 
1992435933ddSDimitry Andric class CommandObjectTargetModulesDumpSymtab
1993435933ddSDimitry Andric     : public CommandObjectTargetModulesModuleAutoComplete {
1994ac7ddfbfSEd Maste public:
CommandObjectTargetModulesDumpSymtab(CommandInterpreter & interpreter)1995435933ddSDimitry Andric   CommandObjectTargetModulesDumpSymtab(CommandInterpreter &interpreter)
1996435933ddSDimitry Andric       : CommandObjectTargetModulesModuleAutoComplete(
1997435933ddSDimitry Andric             interpreter, "target modules dump symtab",
1998435933ddSDimitry Andric             "Dump the symbol table from one or more target modules.", nullptr),
1999435933ddSDimitry Andric         m_options() {}
2000ac7ddfbfSEd Maste 
20014bb0738eSEd Maste   ~CommandObjectTargetModulesDumpSymtab() override = default;
2002ac7ddfbfSEd Maste 
GetOptions()2003435933ddSDimitry Andric   Options *GetOptions() override { return &m_options; }
2004ac7ddfbfSEd Maste 
2005435933ddSDimitry Andric   class CommandOptions : public Options {
2006ac7ddfbfSEd Maste   public:
CommandOptions()2007435933ddSDimitry Andric     CommandOptions() : Options(), m_sort_order(eSortOrderNone) {}
2008ac7ddfbfSEd Maste 
20094bb0738eSEd Maste     ~CommandOptions() override = default;
2010ac7ddfbfSEd Maste 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)20115517e702SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2012435933ddSDimitry Andric                           ExecutionContext *execution_context) override {
20135517e702SDimitry Andric       Status error;
2014ac7ddfbfSEd Maste       const int short_option = m_getopt_table[option_idx].val;
2015ac7ddfbfSEd Maste 
2016435933ddSDimitry Andric       switch (short_option) {
2017ac7ddfbfSEd Maste       case 's':
20184ba319b5SDimitry Andric         m_sort_order = (SortOrder)OptionArgParser::ToOptionEnum(
2019435933ddSDimitry Andric             option_arg, GetDefinitions()[option_idx].enum_values,
2020435933ddSDimitry Andric             eSortOrderNone, error);
2021ac7ddfbfSEd Maste         break;
2022ac7ddfbfSEd Maste 
2023ac7ddfbfSEd Maste       default:
2024435933ddSDimitry Andric         error.SetErrorStringWithFormat("invalid short option character '%c'",
2025435933ddSDimitry Andric                                        short_option);
2026ac7ddfbfSEd Maste         break;
2027ac7ddfbfSEd Maste       }
2028ac7ddfbfSEd Maste       return error;
2029ac7ddfbfSEd Maste     }
2030ac7ddfbfSEd Maste 
OptionParsingStarting(ExecutionContext * execution_context)2031435933ddSDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
2032ac7ddfbfSEd Maste       m_sort_order = eSortOrderNone;
2033ac7ddfbfSEd Maste     }
2034ac7ddfbfSEd Maste 
GetDefinitions()2035435933ddSDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2036435933ddSDimitry Andric       return llvm::makeArrayRef(g_target_modules_dump_symtab_options);
2037ac7ddfbfSEd Maste     }
2038ac7ddfbfSEd Maste 
2039ac7ddfbfSEd Maste     SortOrder m_sort_order;
2040ac7ddfbfSEd Maste   };
2041ac7ddfbfSEd Maste 
2042ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)2043435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
2044ac7ddfbfSEd Maste     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
2045435933ddSDimitry Andric     if (target == nullptr) {
2046435933ddSDimitry Andric       result.AppendError("invalid target, create a debug target using the "
2047435933ddSDimitry Andric                          "'target create' command");
2048ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
2049ac7ddfbfSEd Maste       return false;
2050435933ddSDimitry Andric     } else {
2051ac7ddfbfSEd Maste       uint32_t num_dumped = 0;
2052ac7ddfbfSEd Maste 
2053ac7ddfbfSEd Maste       uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
2054ac7ddfbfSEd Maste       result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2055ac7ddfbfSEd Maste       result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2056ac7ddfbfSEd Maste 
2057435933ddSDimitry Andric       if (command.GetArgumentCount() == 0) {
2058ac7ddfbfSEd Maste         // Dump all sections for all modules images
2059435933ddSDimitry Andric         std::lock_guard<std::recursive_mutex> guard(
2060435933ddSDimitry Andric             target->GetImages().GetMutex());
2061ac7ddfbfSEd Maste         const size_t num_modules = target->GetImages().GetSize();
2062435933ddSDimitry Andric         if (num_modules > 0) {
2063435933ddSDimitry Andric           result.GetOutputStream().Printf("Dumping symbol table for %" PRIu64
2064435933ddSDimitry Andric                                           " modules.\n",
2065435933ddSDimitry Andric                                           (uint64_t)num_modules);
2066435933ddSDimitry Andric           for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
2067435933ddSDimitry Andric             if (num_dumped > 0) {
2068ac7ddfbfSEd Maste               result.GetOutputStream().EOL();
2069ac7ddfbfSEd Maste               result.GetOutputStream().EOL();
2070ac7ddfbfSEd Maste             }
2071acac075bSDimitry Andric             if (m_interpreter.WasInterrupted())
2072acac075bSDimitry Andric               break;
2073ac7ddfbfSEd Maste             num_dumped++;
2074435933ddSDimitry Andric             DumpModuleSymtab(
2075435933ddSDimitry Andric                 m_interpreter, result.GetOutputStream(),
2076ac7ddfbfSEd Maste                 target->GetImages().GetModulePointerAtIndexUnlocked(image_idx),
2077ac7ddfbfSEd Maste                 m_options.m_sort_order);
2078ac7ddfbfSEd Maste           }
2079435933ddSDimitry Andric         } else {
2080ac7ddfbfSEd Maste           result.AppendError("the target has no associated executable images");
2081ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusFailed);
2082ac7ddfbfSEd Maste           return false;
2083ac7ddfbfSEd Maste         }
2084435933ddSDimitry Andric       } else {
2085ac7ddfbfSEd Maste         // Dump specified images (by basename or fullpath)
2086ac7ddfbfSEd Maste         const char *arg_cstr;
2087435933ddSDimitry Andric         for (int arg_idx = 0;
2088435933ddSDimitry Andric              (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
2089435933ddSDimitry Andric              ++arg_idx) {
2090ac7ddfbfSEd Maste           ModuleList module_list;
2091435933ddSDimitry Andric           const size_t num_matches =
2092435933ddSDimitry Andric               FindModulesByName(target, arg_cstr, module_list, true);
2093435933ddSDimitry Andric           if (num_matches > 0) {
2094435933ddSDimitry Andric             for (size_t i = 0; i < num_matches; ++i) {
2095ac7ddfbfSEd Maste               Module *module = module_list.GetModulePointerAtIndex(i);
2096435933ddSDimitry Andric               if (module) {
2097435933ddSDimitry Andric                 if (num_dumped > 0) {
2098ac7ddfbfSEd Maste                   result.GetOutputStream().EOL();
2099ac7ddfbfSEd Maste                   result.GetOutputStream().EOL();
2100ac7ddfbfSEd Maste                 }
2101acac075bSDimitry Andric                 if (m_interpreter.WasInterrupted())
2102acac075bSDimitry Andric                   break;
2103ac7ddfbfSEd Maste                 num_dumped++;
2104435933ddSDimitry Andric                 DumpModuleSymtab(m_interpreter, result.GetOutputStream(),
2105435933ddSDimitry Andric                                  module, m_options.m_sort_order);
2106ac7ddfbfSEd Maste               }
2107ac7ddfbfSEd Maste             }
2108435933ddSDimitry Andric           } else
2109435933ddSDimitry Andric             result.AppendWarningWithFormat(
2110435933ddSDimitry Andric                 "Unable to find an image that matches '%s'.\n", arg_cstr);
2111ac7ddfbfSEd Maste         }
2112ac7ddfbfSEd Maste       }
2113ac7ddfbfSEd Maste 
2114ac7ddfbfSEd Maste       if (num_dumped > 0)
2115ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusSuccessFinishResult);
2116435933ddSDimitry Andric       else {
2117ac7ddfbfSEd Maste         result.AppendError("no matching executable images found");
2118ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
2119ac7ddfbfSEd Maste       }
2120ac7ddfbfSEd Maste     }
2121ac7ddfbfSEd Maste     return result.Succeeded();
2122ac7ddfbfSEd Maste   }
2123ac7ddfbfSEd Maste 
2124ac7ddfbfSEd Maste   CommandOptions m_options;
2125ac7ddfbfSEd Maste };
2126ac7ddfbfSEd Maste 
2127ac7ddfbfSEd Maste #pragma mark CommandObjectTargetModulesDumpSections
2128ac7ddfbfSEd Maste 
2129ac7ddfbfSEd Maste //----------------------------------------------------------------------
2130ac7ddfbfSEd Maste // Image section dumping command
2131ac7ddfbfSEd Maste //----------------------------------------------------------------------
2132ac7ddfbfSEd Maste 
2133435933ddSDimitry Andric class CommandObjectTargetModulesDumpSections
2134435933ddSDimitry Andric     : public CommandObjectTargetModulesModuleAutoComplete {
2135ac7ddfbfSEd Maste public:
CommandObjectTargetModulesDumpSections(CommandInterpreter & interpreter)2136435933ddSDimitry Andric   CommandObjectTargetModulesDumpSections(CommandInterpreter &interpreter)
2137435933ddSDimitry Andric       : CommandObjectTargetModulesModuleAutoComplete(
2138435933ddSDimitry Andric             interpreter, "target modules dump sections",
2139ac7ddfbfSEd Maste             "Dump the sections from one or more target modules.",
2140ac7ddfbfSEd Maste             //"target modules dump sections [<file1> ...]")
2141435933ddSDimitry Andric             nullptr) {}
2142ac7ddfbfSEd Maste 
21434bb0738eSEd Maste   ~CommandObjectTargetModulesDumpSections() override = default;
2144ac7ddfbfSEd Maste 
2145ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)2146435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
2147ac7ddfbfSEd Maste     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
2148435933ddSDimitry Andric     if (target == nullptr) {
2149435933ddSDimitry Andric       result.AppendError("invalid target, create a debug target using the "
2150435933ddSDimitry Andric                          "'target create' command");
2151ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
2152ac7ddfbfSEd Maste       return false;
2153435933ddSDimitry Andric     } else {
2154ac7ddfbfSEd Maste       uint32_t num_dumped = 0;
2155ac7ddfbfSEd Maste 
2156ac7ddfbfSEd Maste       uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
2157ac7ddfbfSEd Maste       result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2158ac7ddfbfSEd Maste       result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2159ac7ddfbfSEd Maste 
2160435933ddSDimitry Andric       if (command.GetArgumentCount() == 0) {
2161ac7ddfbfSEd Maste         // Dump all sections for all modules images
2162ac7ddfbfSEd Maste         const size_t num_modules = target->GetImages().GetSize();
2163435933ddSDimitry Andric         if (num_modules > 0) {
2164435933ddSDimitry Andric           result.GetOutputStream().Printf("Dumping sections for %" PRIu64
2165435933ddSDimitry Andric                                           " modules.\n",
2166435933ddSDimitry Andric                                           (uint64_t)num_modules);
2167435933ddSDimitry Andric           for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
2168acac075bSDimitry Andric             if (m_interpreter.WasInterrupted())
2169acac075bSDimitry Andric               break;
2170ac7ddfbfSEd Maste             num_dumped++;
2171435933ddSDimitry Andric             DumpModuleSections(
2172435933ddSDimitry Andric                 m_interpreter, result.GetOutputStream(),
2173435933ddSDimitry Andric                 target->GetImages().GetModulePointerAtIndex(image_idx));
2174ac7ddfbfSEd Maste           }
2175435933ddSDimitry Andric         } else {
2176ac7ddfbfSEd Maste           result.AppendError("the target has no associated executable images");
2177ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusFailed);
2178ac7ddfbfSEd Maste           return false;
2179ac7ddfbfSEd Maste         }
2180435933ddSDimitry Andric       } else {
2181ac7ddfbfSEd Maste         // Dump specified images (by basename or fullpath)
2182ac7ddfbfSEd Maste         const char *arg_cstr;
2183435933ddSDimitry Andric         for (int arg_idx = 0;
2184435933ddSDimitry Andric              (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
2185435933ddSDimitry Andric              ++arg_idx) {
2186ac7ddfbfSEd Maste           ModuleList module_list;
2187435933ddSDimitry Andric           const size_t num_matches =
2188435933ddSDimitry Andric               FindModulesByName(target, arg_cstr, module_list, true);
2189435933ddSDimitry Andric           if (num_matches > 0) {
2190435933ddSDimitry Andric             for (size_t i = 0; i < num_matches; ++i) {
2191acac075bSDimitry Andric               if (m_interpreter.WasInterrupted())
2192acac075bSDimitry Andric                 break;
2193ac7ddfbfSEd Maste               Module *module = module_list.GetModulePointerAtIndex(i);
2194435933ddSDimitry Andric               if (module) {
2195ac7ddfbfSEd Maste                 num_dumped++;
2196435933ddSDimitry Andric                 DumpModuleSections(m_interpreter, result.GetOutputStream(),
2197435933ddSDimitry Andric                                    module);
2198ac7ddfbfSEd Maste               }
2199ac7ddfbfSEd Maste             }
2200435933ddSDimitry Andric           } else {
2201ac7ddfbfSEd Maste             // Check the global list
2202435933ddSDimitry Andric             std::lock_guard<std::recursive_mutex> guard(
2203435933ddSDimitry Andric                 Module::GetAllocationModuleCollectionMutex());
2204ac7ddfbfSEd Maste 
2205435933ddSDimitry Andric             result.AppendWarningWithFormat(
2206435933ddSDimitry Andric                 "Unable to find an image that matches '%s'.\n", arg_cstr);
2207ac7ddfbfSEd Maste           }
2208ac7ddfbfSEd Maste         }
2209ac7ddfbfSEd Maste       }
2210ac7ddfbfSEd Maste 
2211ac7ddfbfSEd Maste       if (num_dumped > 0)
2212ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusSuccessFinishResult);
2213435933ddSDimitry Andric       else {
2214ac7ddfbfSEd Maste         result.AppendError("no matching executable images found");
2215ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
2216ac7ddfbfSEd Maste       }
2217ac7ddfbfSEd Maste     }
2218ac7ddfbfSEd Maste     return result.Succeeded();
2219ac7ddfbfSEd Maste   }
2220ac7ddfbfSEd Maste };
2221ac7ddfbfSEd Maste 
2222*b5893f02SDimitry Andric #pragma mark CommandObjectTargetModulesDumpSections
2223*b5893f02SDimitry Andric 
2224*b5893f02SDimitry Andric //----------------------------------------------------------------------
2225*b5893f02SDimitry Andric // Clang AST dumping command
2226*b5893f02SDimitry Andric //----------------------------------------------------------------------
2227*b5893f02SDimitry Andric 
2228*b5893f02SDimitry Andric class CommandObjectTargetModulesDumpClangAST
2229*b5893f02SDimitry Andric     : public CommandObjectTargetModulesModuleAutoComplete {
2230*b5893f02SDimitry Andric public:
CommandObjectTargetModulesDumpClangAST(CommandInterpreter & interpreter)2231*b5893f02SDimitry Andric   CommandObjectTargetModulesDumpClangAST(CommandInterpreter &interpreter)
2232*b5893f02SDimitry Andric       : CommandObjectTargetModulesModuleAutoComplete(
2233*b5893f02SDimitry Andric             interpreter, "target modules dump ast",
2234*b5893f02SDimitry Andric             "Dump the clang ast for a given module's symbol file.",
2235*b5893f02SDimitry Andric             //"target modules dump ast [<file1> ...]")
2236*b5893f02SDimitry Andric             nullptr) {}
2237*b5893f02SDimitry Andric 
2238*b5893f02SDimitry Andric   ~CommandObjectTargetModulesDumpClangAST() override = default;
2239*b5893f02SDimitry Andric 
2240*b5893f02SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)2241*b5893f02SDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
2242*b5893f02SDimitry Andric     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
2243*b5893f02SDimitry Andric     if (target == nullptr) {
2244*b5893f02SDimitry Andric       result.AppendError("invalid target, create a debug target using the "
2245*b5893f02SDimitry Andric                          "'target create' command");
2246*b5893f02SDimitry Andric       result.SetStatus(eReturnStatusFailed);
2247*b5893f02SDimitry Andric       return false;
2248*b5893f02SDimitry Andric     }
2249*b5893f02SDimitry Andric 
2250*b5893f02SDimitry Andric     const size_t num_modules = target->GetImages().GetSize();
2251*b5893f02SDimitry Andric     if (num_modules == 0) {
2252*b5893f02SDimitry Andric       result.AppendError("the target has no associated executable images");
2253*b5893f02SDimitry Andric       result.SetStatus(eReturnStatusFailed);
2254*b5893f02SDimitry Andric       return false;
2255*b5893f02SDimitry Andric     }
2256*b5893f02SDimitry Andric 
2257*b5893f02SDimitry Andric     if (command.GetArgumentCount() == 0) {
2258*b5893f02SDimitry Andric       // Dump all ASTs for all modules images
2259*b5893f02SDimitry Andric       result.GetOutputStream().Printf("Dumping clang ast for %" PRIu64
2260*b5893f02SDimitry Andric                                       " modules.\n",
2261*b5893f02SDimitry Andric                                       (uint64_t)num_modules);
2262*b5893f02SDimitry Andric       for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
2263*b5893f02SDimitry Andric         if (m_interpreter.WasInterrupted())
2264*b5893f02SDimitry Andric           break;
2265*b5893f02SDimitry Andric         Module *m = target->GetImages().GetModulePointerAtIndex(image_idx);
2266*b5893f02SDimitry Andric         SymbolFile *sf = m->GetSymbolVendor()->GetSymbolFile();
2267*b5893f02SDimitry Andric         sf->DumpClangAST(result.GetOutputStream());
2268*b5893f02SDimitry Andric       }
2269*b5893f02SDimitry Andric       result.SetStatus(eReturnStatusSuccessFinishResult);
2270*b5893f02SDimitry Andric       return true;
2271*b5893f02SDimitry Andric     }
2272*b5893f02SDimitry Andric 
2273*b5893f02SDimitry Andric     // Dump specified ASTs (by basename or fullpath)
2274*b5893f02SDimitry Andric     for (const Args::ArgEntry &arg : command.entries()) {
2275*b5893f02SDimitry Andric       ModuleList module_list;
2276*b5893f02SDimitry Andric       const size_t num_matches =
2277*b5893f02SDimitry Andric           FindModulesByName(target, arg.c_str(), module_list, true);
2278*b5893f02SDimitry Andric       if (num_matches == 0) {
2279*b5893f02SDimitry Andric         // Check the global list
2280*b5893f02SDimitry Andric         std::lock_guard<std::recursive_mutex> guard(
2281*b5893f02SDimitry Andric             Module::GetAllocationModuleCollectionMutex());
2282*b5893f02SDimitry Andric 
2283*b5893f02SDimitry Andric         result.AppendWarningWithFormat(
2284*b5893f02SDimitry Andric             "Unable to find an image that matches '%s'.\n", arg.c_str());
2285*b5893f02SDimitry Andric         continue;
2286*b5893f02SDimitry Andric       }
2287*b5893f02SDimitry Andric 
2288*b5893f02SDimitry Andric       for (size_t i = 0; i < num_matches; ++i) {
2289*b5893f02SDimitry Andric         if (m_interpreter.WasInterrupted())
2290*b5893f02SDimitry Andric           break;
2291*b5893f02SDimitry Andric         Module *m = module_list.GetModulePointerAtIndex(i);
2292*b5893f02SDimitry Andric         SymbolFile *sf = m->GetSymbolVendor()->GetSymbolFile();
2293*b5893f02SDimitry Andric         sf->DumpClangAST(result.GetOutputStream());
2294*b5893f02SDimitry Andric       }
2295*b5893f02SDimitry Andric     }
2296*b5893f02SDimitry Andric     result.SetStatus(eReturnStatusSuccessFinishResult);
2297*b5893f02SDimitry Andric     return true;
2298*b5893f02SDimitry Andric   }
2299*b5893f02SDimitry Andric };
2300*b5893f02SDimitry Andric 
2301ac7ddfbfSEd Maste #pragma mark CommandObjectTargetModulesDumpSymfile
2302ac7ddfbfSEd Maste 
2303ac7ddfbfSEd Maste //----------------------------------------------------------------------
2304ac7ddfbfSEd Maste // Image debug symbol dumping command
2305ac7ddfbfSEd Maste //----------------------------------------------------------------------
2306ac7ddfbfSEd Maste 
2307435933ddSDimitry Andric class CommandObjectTargetModulesDumpSymfile
2308435933ddSDimitry Andric     : public CommandObjectTargetModulesModuleAutoComplete {
2309ac7ddfbfSEd Maste public:
CommandObjectTargetModulesDumpSymfile(CommandInterpreter & interpreter)2310435933ddSDimitry Andric   CommandObjectTargetModulesDumpSymfile(CommandInterpreter &interpreter)
2311435933ddSDimitry Andric       : CommandObjectTargetModulesModuleAutoComplete(
2312435933ddSDimitry Andric             interpreter, "target modules dump symfile",
2313ac7ddfbfSEd Maste             "Dump the debug symbol file for one or more target modules.",
2314ac7ddfbfSEd Maste             //"target modules dump symfile [<file1> ...]")
2315435933ddSDimitry Andric             nullptr) {}
2316ac7ddfbfSEd Maste 
23174bb0738eSEd Maste   ~CommandObjectTargetModulesDumpSymfile() override = default;
2318ac7ddfbfSEd Maste 
2319ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)2320435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
2321ac7ddfbfSEd Maste     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
2322435933ddSDimitry Andric     if (target == nullptr) {
2323435933ddSDimitry Andric       result.AppendError("invalid target, create a debug target using the "
2324435933ddSDimitry Andric                          "'target create' command");
2325ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
2326ac7ddfbfSEd Maste       return false;
2327435933ddSDimitry Andric     } else {
2328ac7ddfbfSEd Maste       uint32_t num_dumped = 0;
2329ac7ddfbfSEd Maste 
2330ac7ddfbfSEd Maste       uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
2331ac7ddfbfSEd Maste       result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2332ac7ddfbfSEd Maste       result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2333ac7ddfbfSEd Maste 
2334435933ddSDimitry Andric       if (command.GetArgumentCount() == 0) {
2335ac7ddfbfSEd Maste         // Dump all sections for all modules images
2336ac7ddfbfSEd Maste         const ModuleList &target_modules = target->GetImages();
23374bb0738eSEd Maste         std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
2338ac7ddfbfSEd Maste         const size_t num_modules = target_modules.GetSize();
2339435933ddSDimitry Andric         if (num_modules > 0) {
2340435933ddSDimitry Andric           result.GetOutputStream().Printf("Dumping debug symbols for %" PRIu64
2341435933ddSDimitry Andric                                           " modules.\n",
2342435933ddSDimitry Andric                                           (uint64_t)num_modules);
2343435933ddSDimitry Andric           for (uint32_t image_idx = 0; image_idx < num_modules; ++image_idx) {
2344acac075bSDimitry Andric             if (m_interpreter.WasInterrupted())
2345acac075bSDimitry Andric               break;
2346435933ddSDimitry Andric             if (DumpModuleSymbolVendor(
2347435933ddSDimitry Andric                     result.GetOutputStream(),
2348435933ddSDimitry Andric                     target_modules.GetModulePointerAtIndexUnlocked(image_idx)))
2349ac7ddfbfSEd Maste               num_dumped++;
2350ac7ddfbfSEd Maste           }
2351435933ddSDimitry Andric         } else {
2352ac7ddfbfSEd Maste           result.AppendError("the target has no associated executable images");
2353ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusFailed);
2354ac7ddfbfSEd Maste           return false;
2355ac7ddfbfSEd Maste         }
2356435933ddSDimitry Andric       } else {
2357ac7ddfbfSEd Maste         // Dump specified images (by basename or fullpath)
2358ac7ddfbfSEd Maste         const char *arg_cstr;
2359435933ddSDimitry Andric         for (int arg_idx = 0;
2360435933ddSDimitry Andric              (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
2361435933ddSDimitry Andric              ++arg_idx) {
2362ac7ddfbfSEd Maste           ModuleList module_list;
2363435933ddSDimitry Andric           const size_t num_matches =
2364435933ddSDimitry Andric               FindModulesByName(target, arg_cstr, module_list, true);
2365435933ddSDimitry Andric           if (num_matches > 0) {
2366435933ddSDimitry Andric             for (size_t i = 0; i < num_matches; ++i) {
2367acac075bSDimitry Andric               if (m_interpreter.WasInterrupted())
2368acac075bSDimitry Andric                 break;
2369ac7ddfbfSEd Maste               Module *module = module_list.GetModulePointerAtIndex(i);
2370435933ddSDimitry Andric               if (module) {
2371ac7ddfbfSEd Maste                 if (DumpModuleSymbolVendor(result.GetOutputStream(), module))
2372ac7ddfbfSEd Maste                   num_dumped++;
2373ac7ddfbfSEd Maste               }
2374ac7ddfbfSEd Maste             }
2375435933ddSDimitry Andric           } else
2376435933ddSDimitry Andric             result.AppendWarningWithFormat(
2377435933ddSDimitry Andric                 "Unable to find an image that matches '%s'.\n", arg_cstr);
2378ac7ddfbfSEd Maste         }
2379ac7ddfbfSEd Maste       }
2380ac7ddfbfSEd Maste 
2381ac7ddfbfSEd Maste       if (num_dumped > 0)
2382ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusSuccessFinishResult);
2383435933ddSDimitry Andric       else {
2384ac7ddfbfSEd Maste         result.AppendError("no matching executable images found");
2385ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
2386ac7ddfbfSEd Maste       }
2387ac7ddfbfSEd Maste     }
2388ac7ddfbfSEd Maste     return result.Succeeded();
2389ac7ddfbfSEd Maste   }
2390ac7ddfbfSEd Maste };
2391ac7ddfbfSEd Maste 
2392ac7ddfbfSEd Maste #pragma mark CommandObjectTargetModulesDumpLineTable
2393ac7ddfbfSEd Maste 
2394ac7ddfbfSEd Maste //----------------------------------------------------------------------
2395ac7ddfbfSEd Maste // Image debug line table dumping command
2396ac7ddfbfSEd Maste //----------------------------------------------------------------------
2397ac7ddfbfSEd Maste 
2398435933ddSDimitry Andric class CommandObjectTargetModulesDumpLineTable
2399435933ddSDimitry Andric     : public CommandObjectTargetModulesSourceFileAutoComplete {
2400ac7ddfbfSEd Maste public:
CommandObjectTargetModulesDumpLineTable(CommandInterpreter & interpreter)2401435933ddSDimitry Andric   CommandObjectTargetModulesDumpLineTable(CommandInterpreter &interpreter)
2402435933ddSDimitry Andric       : CommandObjectTargetModulesSourceFileAutoComplete(
2403435933ddSDimitry Andric             interpreter, "target modules dump line-table",
2404435933ddSDimitry Andric             "Dump the line table for one or more compilation units.", nullptr,
2405435933ddSDimitry Andric             eCommandRequiresTarget) {}
2406ac7ddfbfSEd Maste 
24074bb0738eSEd Maste   ~CommandObjectTargetModulesDumpLineTable() override = default;
2408ac7ddfbfSEd Maste 
2409ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)2410435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
2411ac7ddfbfSEd Maste     Target *target = m_exe_ctx.GetTargetPtr();
2412ac7ddfbfSEd Maste     uint32_t total_num_dumped = 0;
2413ac7ddfbfSEd Maste 
2414ac7ddfbfSEd Maste     uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
2415ac7ddfbfSEd Maste     result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2416ac7ddfbfSEd Maste     result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2417ac7ddfbfSEd Maste 
2418435933ddSDimitry Andric     if (command.GetArgumentCount() == 0) {
2419a1bd240cSDimitry Andric       result.AppendError("file option must be specified.");
2420ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
2421a1bd240cSDimitry Andric       return result.Succeeded();
2422435933ddSDimitry Andric     } else {
2423ac7ddfbfSEd Maste       // Dump specified images (by basename or fullpath)
2424ac7ddfbfSEd Maste       const char *arg_cstr;
2425435933ddSDimitry Andric       for (int arg_idx = 0;
2426435933ddSDimitry Andric            (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
2427435933ddSDimitry Andric            ++arg_idx) {
2428*b5893f02SDimitry Andric         FileSpec file_spec(arg_cstr);
2429ac7ddfbfSEd Maste 
2430ac7ddfbfSEd Maste         const ModuleList &target_modules = target->GetImages();
24314bb0738eSEd Maste         std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
2432ac7ddfbfSEd Maste         const size_t num_modules = target_modules.GetSize();
2433435933ddSDimitry Andric         if (num_modules > 0) {
2434ac7ddfbfSEd Maste           uint32_t num_dumped = 0;
2435435933ddSDimitry Andric           for (uint32_t i = 0; i < num_modules; ++i) {
2436acac075bSDimitry Andric             if (m_interpreter.WasInterrupted())
2437acac075bSDimitry Andric               break;
2438435933ddSDimitry Andric             if (DumpCompileUnitLineTable(
2439435933ddSDimitry Andric                     m_interpreter, result.GetOutputStream(),
2440ac7ddfbfSEd Maste                     target_modules.GetModulePointerAtIndexUnlocked(i),
2441435933ddSDimitry Andric                     file_spec, m_exe_ctx.GetProcessPtr() &&
2442435933ddSDimitry Andric                                    m_exe_ctx.GetProcessRef().IsAlive()))
2443ac7ddfbfSEd Maste               num_dumped++;
2444ac7ddfbfSEd Maste           }
2445ac7ddfbfSEd Maste           if (num_dumped == 0)
2446435933ddSDimitry Andric             result.AppendWarningWithFormat(
2447435933ddSDimitry Andric                 "No source filenames matched '%s'.\n", arg_cstr);
2448ac7ddfbfSEd Maste           else
2449ac7ddfbfSEd Maste             total_num_dumped += num_dumped;
2450ac7ddfbfSEd Maste         }
2451ac7ddfbfSEd Maste       }
2452ac7ddfbfSEd Maste     }
2453ac7ddfbfSEd Maste 
2454ac7ddfbfSEd Maste     if (total_num_dumped > 0)
2455ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusSuccessFinishResult);
2456435933ddSDimitry Andric     else {
2457ac7ddfbfSEd Maste       result.AppendError("no source filenames matched any command arguments");
2458ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
2459ac7ddfbfSEd Maste     }
2460ac7ddfbfSEd Maste     return result.Succeeded();
2461ac7ddfbfSEd Maste   }
2462ac7ddfbfSEd Maste };
2463ac7ddfbfSEd Maste 
2464ac7ddfbfSEd Maste #pragma mark CommandObjectTargetModulesDump
2465ac7ddfbfSEd Maste 
2466ac7ddfbfSEd Maste //----------------------------------------------------------------------
2467ac7ddfbfSEd Maste // Dump multi-word command for target modules
2468ac7ddfbfSEd Maste //----------------------------------------------------------------------
2469ac7ddfbfSEd Maste 
2470435933ddSDimitry Andric class CommandObjectTargetModulesDump : public CommandObjectMultiword {
2471ac7ddfbfSEd Maste public:
2472ac7ddfbfSEd Maste   //------------------------------------------------------------------
2473ac7ddfbfSEd Maste   // Constructors and Destructors
2474ac7ddfbfSEd Maste   //------------------------------------------------------------------
CommandObjectTargetModulesDump(CommandInterpreter & interpreter)24754bb0738eSEd Maste   CommandObjectTargetModulesDump(CommandInterpreter &interpreter)
2476*b5893f02SDimitry Andric       : CommandObjectMultiword(
2477*b5893f02SDimitry Andric             interpreter, "target modules dump",
2478435933ddSDimitry Andric             "Commands for dumping information about one or "
2479435933ddSDimitry Andric             "more target modules.",
2480435933ddSDimitry Andric             "target modules dump "
2481*b5893f02SDimitry Andric             "[headers|symtab|sections|ast|symfile|line-table] "
2482435933ddSDimitry Andric             "[<file1> <file2> ...]") {
2483435933ddSDimitry Andric     LoadSubCommand("objfile",
2484435933ddSDimitry Andric                    CommandObjectSP(
2485435933ddSDimitry Andric                        new CommandObjectTargetModulesDumpObjfile(interpreter)));
2486435933ddSDimitry Andric     LoadSubCommand(
2487435933ddSDimitry Andric         "symtab",
2488435933ddSDimitry Andric         CommandObjectSP(new CommandObjectTargetModulesDumpSymtab(interpreter)));
2489435933ddSDimitry Andric     LoadSubCommand("sections",
2490435933ddSDimitry Andric                    CommandObjectSP(new CommandObjectTargetModulesDumpSections(
2491435933ddSDimitry Andric                        interpreter)));
2492435933ddSDimitry Andric     LoadSubCommand("symfile",
2493435933ddSDimitry Andric                    CommandObjectSP(
2494435933ddSDimitry Andric                        new CommandObjectTargetModulesDumpSymfile(interpreter)));
2495*b5893f02SDimitry Andric     LoadSubCommand(
2496*b5893f02SDimitry Andric         "ast", CommandObjectSP(
2497*b5893f02SDimitry Andric                    new CommandObjectTargetModulesDumpClangAST(interpreter)));
2498435933ddSDimitry Andric     LoadSubCommand("line-table",
2499435933ddSDimitry Andric                    CommandObjectSP(new CommandObjectTargetModulesDumpLineTable(
2500435933ddSDimitry Andric                        interpreter)));
2501ac7ddfbfSEd Maste   }
2502ac7ddfbfSEd Maste 
25034bb0738eSEd Maste   ~CommandObjectTargetModulesDump() override = default;
2504ac7ddfbfSEd Maste };
2505ac7ddfbfSEd Maste 
2506435933ddSDimitry Andric class CommandObjectTargetModulesAdd : public CommandObjectParsed {
2507ac7ddfbfSEd Maste public:
CommandObjectTargetModulesAdd(CommandInterpreter & interpreter)2508435933ddSDimitry Andric   CommandObjectTargetModulesAdd(CommandInterpreter &interpreter)
2509435933ddSDimitry Andric       : CommandObjectParsed(interpreter, "target modules add",
2510ac7ddfbfSEd Maste                             "Add a new module to the current target's modules.",
2511ac7ddfbfSEd Maste                             "target modules add [<module>]"),
2512435933ddSDimitry Andric         m_option_group(),
2513435933ddSDimitry Andric         m_symbol_file(LLDB_OPT_SET_1, false, "symfile", 's', 0,
2514435933ddSDimitry Andric                       eArgTypeFilename, "Fullpath to a stand alone debug "
2515435933ddSDimitry Andric                                         "symbols file for when debug symbols "
2516435933ddSDimitry Andric                                         "are not in the executable.") {
2517435933ddSDimitry Andric     m_option_group.Append(&m_uuid_option_group, LLDB_OPT_SET_ALL,
2518435933ddSDimitry Andric                           LLDB_OPT_SET_1);
2519ac7ddfbfSEd Maste     m_option_group.Append(&m_symbol_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2520ac7ddfbfSEd Maste     m_option_group.Finalize();
2521ac7ddfbfSEd Maste   }
2522ac7ddfbfSEd Maste 
25234bb0738eSEd Maste   ~CommandObjectTargetModulesAdd() override = default;
2524ac7ddfbfSEd Maste 
GetOptions()2525435933ddSDimitry Andric   Options *GetOptions() override { return &m_option_group; }
2526ac7ddfbfSEd Maste 
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)25274ba319b5SDimitry Andric   int HandleArgumentCompletion(
25284ba319b5SDimitry Andric       CompletionRequest &request,
25294ba319b5SDimitry Andric       OptionElementVector &opt_element_vector) override {
2530435933ddSDimitry Andric     CommandCompletions::InvokeCommonCompletionCallbacks(
2531435933ddSDimitry Andric         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
25324ba319b5SDimitry Andric         request, nullptr);
25334ba319b5SDimitry Andric     return request.GetNumberOfMatches();
2534ac7ddfbfSEd Maste   }
2535ac7ddfbfSEd Maste 
2536ac7ddfbfSEd Maste protected:
2537ac7ddfbfSEd Maste   OptionGroupOptions m_option_group;
2538ac7ddfbfSEd Maste   OptionGroupUUID m_uuid_option_group;
2539ac7ddfbfSEd Maste   OptionGroupFile m_symbol_file;
2540ac7ddfbfSEd Maste 
DoExecute(Args & args,CommandReturnObject & result)2541435933ddSDimitry Andric   bool DoExecute(Args &args, CommandReturnObject &result) override {
2542ac7ddfbfSEd Maste     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
2543435933ddSDimitry Andric     if (target == nullptr) {
2544435933ddSDimitry Andric       result.AppendError("invalid target, create a debug target using the "
2545435933ddSDimitry Andric                          "'target create' command");
2546ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
2547ac7ddfbfSEd Maste       return false;
2548435933ddSDimitry Andric     } else {
2549ac7ddfbfSEd Maste       bool flush = false;
2550ac7ddfbfSEd Maste 
2551ac7ddfbfSEd Maste       const size_t argc = args.GetArgumentCount();
2552435933ddSDimitry Andric       if (argc == 0) {
2553435933ddSDimitry Andric         if (m_uuid_option_group.GetOptionValue().OptionWasSet()) {
2554ac7ddfbfSEd Maste           // We are given a UUID only, go locate the file
2555ac7ddfbfSEd Maste           ModuleSpec module_spec;
2556435933ddSDimitry Andric           module_spec.GetUUID() =
2557435933ddSDimitry Andric               m_uuid_option_group.GetOptionValue().GetCurrentValue();
2558ac7ddfbfSEd Maste           if (m_symbol_file.GetOptionValue().OptionWasSet())
2559435933ddSDimitry Andric             module_spec.GetSymbolFileSpec() =
2560435933ddSDimitry Andric                 m_symbol_file.GetOptionValue().GetCurrentValue();
2561435933ddSDimitry Andric           if (Symbols::DownloadObjectAndSymbolFile(module_spec)) {
2562ac7ddfbfSEd Maste             ModuleSP module_sp(target->GetSharedModule(module_spec));
2563435933ddSDimitry Andric             if (module_sp) {
2564ac7ddfbfSEd Maste               result.SetStatus(eReturnStatusSuccessFinishResult);
2565ac7ddfbfSEd Maste               return true;
2566435933ddSDimitry Andric             } else {
2567ac7ddfbfSEd Maste               StreamString strm;
2568ac7ddfbfSEd Maste               module_spec.GetUUID().Dump(&strm);
2569435933ddSDimitry Andric               if (module_spec.GetFileSpec()) {
2570435933ddSDimitry Andric                 if (module_spec.GetSymbolFileSpec()) {
2571435933ddSDimitry Andric                   result.AppendErrorWithFormat(
2572435933ddSDimitry Andric                       "Unable to create the executable or symbol file with "
2573435933ddSDimitry Andric                       "UUID %s with path %s and symbol file %s",
2574435933ddSDimitry Andric                       strm.GetData(),
2575ac7ddfbfSEd Maste                       module_spec.GetFileSpec().GetPath().c_str(),
2576ac7ddfbfSEd Maste                       module_spec.GetSymbolFileSpec().GetPath().c_str());
2577435933ddSDimitry Andric                 } else {
2578435933ddSDimitry Andric                   result.AppendErrorWithFormat(
2579435933ddSDimitry Andric                       "Unable to create the executable or symbol file with "
2580435933ddSDimitry Andric                       "UUID %s with path %s",
2581435933ddSDimitry Andric                       strm.GetData(),
2582ac7ddfbfSEd Maste                       module_spec.GetFileSpec().GetPath().c_str());
2583ac7ddfbfSEd Maste                 }
2584435933ddSDimitry Andric               } else {
2585435933ddSDimitry Andric                 result.AppendErrorWithFormat("Unable to create the executable "
2586435933ddSDimitry Andric                                              "or symbol file with UUID %s",
2587435933ddSDimitry Andric                                              strm.GetData());
2588ac7ddfbfSEd Maste               }
2589ac7ddfbfSEd Maste               result.SetStatus(eReturnStatusFailed);
2590ac7ddfbfSEd Maste               return false;
2591ac7ddfbfSEd Maste             }
2592435933ddSDimitry Andric           } else {
2593ac7ddfbfSEd Maste             StreamString strm;
2594ac7ddfbfSEd Maste             module_spec.GetUUID().Dump(&strm);
2595435933ddSDimitry Andric             result.AppendErrorWithFormat(
2596435933ddSDimitry Andric                 "Unable to locate the executable or symbol file with UUID %s",
2597435933ddSDimitry Andric                 strm.GetData());
2598ac7ddfbfSEd Maste             result.SetStatus(eReturnStatusFailed);
2599ac7ddfbfSEd Maste             return false;
2600ac7ddfbfSEd Maste           }
2601435933ddSDimitry Andric         } else {
2602435933ddSDimitry Andric           result.AppendError(
2603435933ddSDimitry Andric               "one or more executable image paths must be specified");
2604ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusFailed);
2605ac7ddfbfSEd Maste           return false;
2606ac7ddfbfSEd Maste         }
2607435933ddSDimitry Andric       } else {
2608435933ddSDimitry Andric         for (auto &entry : args.entries()) {
2609435933ddSDimitry Andric           if (entry.ref.empty())
2610435933ddSDimitry Andric             continue;
2611435933ddSDimitry Andric 
2612*b5893f02SDimitry Andric           FileSpec file_spec(entry.ref);
2613*b5893f02SDimitry Andric           if (FileSystem::Instance().Exists(file_spec)) {
2614ac7ddfbfSEd Maste             ModuleSpec module_spec(file_spec);
2615ac7ddfbfSEd Maste             if (m_uuid_option_group.GetOptionValue().OptionWasSet())
2616435933ddSDimitry Andric               module_spec.GetUUID() =
2617435933ddSDimitry Andric                   m_uuid_option_group.GetOptionValue().GetCurrentValue();
2618ac7ddfbfSEd Maste             if (m_symbol_file.GetOptionValue().OptionWasSet())
2619435933ddSDimitry Andric               module_spec.GetSymbolFileSpec() =
2620435933ddSDimitry Andric                   m_symbol_file.GetOptionValue().GetCurrentValue();
262135617911SEd Maste             if (!module_spec.GetArchitecture().IsValid())
262235617911SEd Maste               module_spec.GetArchitecture() = target->GetArchitecture();
26235517e702SDimitry Andric             Status error;
2624ac7ddfbfSEd Maste             ModuleSP module_sp(target->GetSharedModule(module_spec, &error));
2625435933ddSDimitry Andric             if (!module_sp) {
2626ac7ddfbfSEd Maste               const char *error_cstr = error.AsCString();
2627ac7ddfbfSEd Maste               if (error_cstr)
2628ac7ddfbfSEd Maste                 result.AppendError(error_cstr);
2629ac7ddfbfSEd Maste               else
2630435933ddSDimitry Andric                 result.AppendErrorWithFormat("unsupported module: %s",
2631435933ddSDimitry Andric                                              entry.c_str());
2632ac7ddfbfSEd Maste               result.SetStatus(eReturnStatusFailed);
2633ac7ddfbfSEd Maste               return false;
2634435933ddSDimitry Andric             } else {
2635ac7ddfbfSEd Maste               flush = true;
2636ac7ddfbfSEd Maste             }
2637ac7ddfbfSEd Maste             result.SetStatus(eReturnStatusSuccessFinishResult);
2638435933ddSDimitry Andric           } else {
2639435933ddSDimitry Andric             std::string resolved_path = file_spec.GetPath();
2640ac7ddfbfSEd Maste             result.SetStatus(eReturnStatusFailed);
2641435933ddSDimitry Andric             if (resolved_path != entry.ref) {
2642435933ddSDimitry Andric               result.AppendErrorWithFormat(
2643435933ddSDimitry Andric                   "invalid module path '%s' with resolved path '%s'\n",
2644435933ddSDimitry Andric                   entry.ref.str().c_str(), resolved_path.c_str());
2645ac7ddfbfSEd Maste               break;
2646ac7ddfbfSEd Maste             }
2647435933ddSDimitry Andric             result.AppendErrorWithFormat("invalid module path '%s'\n",
2648435933ddSDimitry Andric                                          entry.c_str());
2649ac7ddfbfSEd Maste             break;
2650ac7ddfbfSEd Maste           }
2651ac7ddfbfSEd Maste         }
2652ac7ddfbfSEd Maste       }
2653ac7ddfbfSEd Maste 
2654435933ddSDimitry Andric       if (flush) {
2655ac7ddfbfSEd Maste         ProcessSP process = target->GetProcessSP();
2656ac7ddfbfSEd Maste         if (process)
2657ac7ddfbfSEd Maste           process->Flush();
2658ac7ddfbfSEd Maste       }
2659ac7ddfbfSEd Maste     }
2660ac7ddfbfSEd Maste 
2661ac7ddfbfSEd Maste     return result.Succeeded();
2662ac7ddfbfSEd Maste   }
2663ac7ddfbfSEd Maste };
2664ac7ddfbfSEd Maste 
2665435933ddSDimitry Andric class CommandObjectTargetModulesLoad
2666435933ddSDimitry Andric     : public CommandObjectTargetModulesModuleAutoComplete {
2667ac7ddfbfSEd Maste public:
CommandObjectTargetModulesLoad(CommandInterpreter & interpreter)2668435933ddSDimitry Andric   CommandObjectTargetModulesLoad(CommandInterpreter &interpreter)
2669435933ddSDimitry Andric       : CommandObjectTargetModulesModuleAutoComplete(
2670435933ddSDimitry Andric             interpreter, "target modules load", "Set the load addresses for "
2671435933ddSDimitry Andric                                                 "one or more sections in a "
2672435933ddSDimitry Andric                                                 "target module.",
2673435933ddSDimitry Andric             "target modules load [--file <module> --uuid <uuid>] <sect-name> "
2674435933ddSDimitry Andric             "<address> [<sect-name> <address> ....]"),
2675435933ddSDimitry Andric         m_option_group(),
2676435933ddSDimitry Andric         m_file_option(LLDB_OPT_SET_1, false, "file", 'f', 0, eArgTypeName,
2677435933ddSDimitry Andric                       "Fullpath or basename for module to load.", ""),
2678f678e45dSDimitry Andric         m_load_option(LLDB_OPT_SET_1, false, "load", 'l',
2679f678e45dSDimitry Andric                       "Write file contents to the memory.", false, true),
2680acac075bSDimitry Andric         m_pc_option(LLDB_OPT_SET_1, false, "set-pc-to-entry", 'p',
2681f678e45dSDimitry Andric                     "Set PC to the entry point."
2682f678e45dSDimitry Andric                     " Only applicable with '--load' option.",
2683f678e45dSDimitry Andric                     false, true),
2684435933ddSDimitry Andric         m_slide_option(LLDB_OPT_SET_1, false, "slide", 's', 0, eArgTypeOffset,
2685435933ddSDimitry Andric                        "Set the load address for all sections to be the "
2686435933ddSDimitry Andric                        "virtual address in the file plus the offset.",
2687435933ddSDimitry Andric                        0) {
2688435933ddSDimitry Andric     m_option_group.Append(&m_uuid_option_group, LLDB_OPT_SET_ALL,
2689435933ddSDimitry Andric                           LLDB_OPT_SET_1);
2690ac7ddfbfSEd Maste     m_option_group.Append(&m_file_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2691f678e45dSDimitry Andric     m_option_group.Append(&m_load_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2692f678e45dSDimitry Andric     m_option_group.Append(&m_pc_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2693ac7ddfbfSEd Maste     m_option_group.Append(&m_slide_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2694ac7ddfbfSEd Maste     m_option_group.Finalize();
2695ac7ddfbfSEd Maste   }
2696ac7ddfbfSEd Maste 
26974bb0738eSEd Maste   ~CommandObjectTargetModulesLoad() override = default;
2698ac7ddfbfSEd Maste 
GetOptions()2699435933ddSDimitry Andric   Options *GetOptions() override { return &m_option_group; }
2700ac7ddfbfSEd Maste 
2701ac7ddfbfSEd Maste protected:
DoExecute(Args & args,CommandReturnObject & result)2702435933ddSDimitry Andric   bool DoExecute(Args &args, CommandReturnObject &result) override {
2703ac7ddfbfSEd Maste     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
2704f678e45dSDimitry Andric     const bool load = m_load_option.GetOptionValue().GetCurrentValue();
2705f678e45dSDimitry Andric     const bool set_pc = m_pc_option.GetOptionValue().GetCurrentValue();
2706435933ddSDimitry Andric     if (target == nullptr) {
2707435933ddSDimitry Andric       result.AppendError("invalid target, create a debug target using the "
2708435933ddSDimitry Andric                          "'target create' command");
2709ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
2710ac7ddfbfSEd Maste       return false;
2711435933ddSDimitry Andric     } else {
2712ac7ddfbfSEd Maste       const size_t argc = args.GetArgumentCount();
2713ac7ddfbfSEd Maste       ModuleSpec module_spec;
2714ac7ddfbfSEd Maste       bool search_using_module_spec = false;
2715f678e45dSDimitry Andric 
27164ba319b5SDimitry Andric       // Allow "load" option to work without --file or --uuid option.
2717f678e45dSDimitry Andric       if (load) {
2718f678e45dSDimitry Andric         if (!m_file_option.GetOptionValue().OptionWasSet() &&
2719f678e45dSDimitry Andric             !m_uuid_option_group.GetOptionValue().OptionWasSet()) {
2720f678e45dSDimitry Andric           ModuleList &module_list = target->GetImages();
2721f678e45dSDimitry Andric           if (module_list.GetSize() == 1) {
2722f678e45dSDimitry Andric             search_using_module_spec = true;
2723f678e45dSDimitry Andric             module_spec.GetFileSpec() =
2724f678e45dSDimitry Andric                 module_list.GetModuleAtIndex(0)->GetFileSpec();
2725f678e45dSDimitry Andric           }
2726f678e45dSDimitry Andric         }
2727f678e45dSDimitry Andric       }
2728f678e45dSDimitry Andric 
2729435933ddSDimitry Andric       if (m_file_option.GetOptionValue().OptionWasSet()) {
2730ac7ddfbfSEd Maste         search_using_module_spec = true;
27317aa51b79SEd Maste         const char *arg_cstr = m_file_option.GetOptionValue().GetCurrentValue();
27327aa51b79SEd Maste         const bool use_global_module_list = true;
27337aa51b79SEd Maste         ModuleList module_list;
2734435933ddSDimitry Andric         const size_t num_matches = FindModulesByName(
2735435933ddSDimitry Andric             target, arg_cstr, module_list, use_global_module_list);
2736435933ddSDimitry Andric         if (num_matches == 1) {
2737435933ddSDimitry Andric           module_spec.GetFileSpec() =
2738435933ddSDimitry Andric               module_list.GetModuleAtIndex(0)->GetFileSpec();
2739435933ddSDimitry Andric         } else if (num_matches > 1) {
27407aa51b79SEd Maste           search_using_module_spec = false;
2741435933ddSDimitry Andric           result.AppendErrorWithFormat(
2742435933ddSDimitry Andric               "more than 1 module matched by name '%s'\n", arg_cstr);
27437aa51b79SEd Maste           result.SetStatus(eReturnStatusFailed);
2744435933ddSDimitry Andric         } else {
27457aa51b79SEd Maste           search_using_module_spec = false;
2746435933ddSDimitry Andric           result.AppendErrorWithFormat("no object file for module '%s'\n",
2747435933ddSDimitry Andric                                        arg_cstr);
27487aa51b79SEd Maste           result.SetStatus(eReturnStatusFailed);
27497aa51b79SEd Maste         }
2750ac7ddfbfSEd Maste       }
2751ac7ddfbfSEd Maste 
2752435933ddSDimitry Andric       if (m_uuid_option_group.GetOptionValue().OptionWasSet()) {
2753ac7ddfbfSEd Maste         search_using_module_spec = true;
2754435933ddSDimitry Andric         module_spec.GetUUID() =
2755435933ddSDimitry Andric             m_uuid_option_group.GetOptionValue().GetCurrentValue();
2756ac7ddfbfSEd Maste       }
2757ac7ddfbfSEd Maste 
2758435933ddSDimitry Andric       if (search_using_module_spec) {
2759ac7ddfbfSEd Maste         ModuleList matching_modules;
2760435933ddSDimitry Andric         const size_t num_matches =
2761435933ddSDimitry Andric             target->GetImages().FindModules(module_spec, matching_modules);
2762ac7ddfbfSEd Maste 
2763ac7ddfbfSEd Maste         char path[PATH_MAX];
2764435933ddSDimitry Andric         if (num_matches == 1) {
2765ac7ddfbfSEd Maste           Module *module = matching_modules.GetModulePointerAtIndex(0);
2766435933ddSDimitry Andric           if (module) {
2767ac7ddfbfSEd Maste             ObjectFile *objfile = module->GetObjectFile();
2768435933ddSDimitry Andric             if (objfile) {
2769ac7ddfbfSEd Maste               SectionList *section_list = module->GetSectionList();
2770435933ddSDimitry Andric               if (section_list) {
2771ac7ddfbfSEd Maste                 bool changed = false;
2772435933ddSDimitry Andric                 if (argc == 0) {
2773435933ddSDimitry Andric                   if (m_slide_option.GetOptionValue().OptionWasSet()) {
2774435933ddSDimitry Andric                     const addr_t slide =
2775435933ddSDimitry Andric                         m_slide_option.GetOptionValue().GetCurrentValue();
277612b93ac6SEd Maste                     const bool slide_is_offset = true;
2777435933ddSDimitry Andric                     module->SetLoadAddress(*target, slide, slide_is_offset,
2778435933ddSDimitry Andric                                            changed);
2779435933ddSDimitry Andric                   } else {
2780435933ddSDimitry Andric                     result.AppendError("one or more section name + load "
2781435933ddSDimitry Andric                                        "address pair must be specified");
2782ac7ddfbfSEd Maste                     result.SetStatus(eReturnStatusFailed);
2783ac7ddfbfSEd Maste                     return false;
2784ac7ddfbfSEd Maste                   }
2785435933ddSDimitry Andric                 } else {
2786435933ddSDimitry Andric                   if (m_slide_option.GetOptionValue().OptionWasSet()) {
2787435933ddSDimitry Andric                     result.AppendError("The \"--slide <offset>\" option can't "
2788435933ddSDimitry Andric                                        "be used in conjunction with setting "
2789435933ddSDimitry Andric                                        "section load addresses.\n");
2790ac7ddfbfSEd Maste                     result.SetStatus(eReturnStatusFailed);
2791ac7ddfbfSEd Maste                     return false;
2792ac7ddfbfSEd Maste                   }
2793ac7ddfbfSEd Maste 
2794435933ddSDimitry Andric                   for (size_t i = 0; i < argc; i += 2) {
2795ac7ddfbfSEd Maste                     const char *sect_name = args.GetArgumentAtIndex(i);
2796ac7ddfbfSEd Maste                     const char *load_addr_cstr = args.GetArgumentAtIndex(i + 1);
2797435933ddSDimitry Andric                     if (sect_name && load_addr_cstr) {
2798ac7ddfbfSEd Maste                       ConstString const_sect_name(sect_name);
2799ac7ddfbfSEd Maste                       bool success = false;
2800435933ddSDimitry Andric                       addr_t load_addr = StringConvert::ToUInt64(
2801435933ddSDimitry Andric                           load_addr_cstr, LLDB_INVALID_ADDRESS, 0, &success);
2802435933ddSDimitry Andric                       if (success) {
2803435933ddSDimitry Andric                         SectionSP section_sp(
2804435933ddSDimitry Andric                             section_list->FindSectionByName(const_sect_name));
2805435933ddSDimitry Andric                         if (section_sp) {
2806435933ddSDimitry Andric                           if (section_sp->IsThreadSpecific()) {
2807435933ddSDimitry Andric                             result.AppendErrorWithFormat(
2808435933ddSDimitry Andric                                 "thread specific sections are not yet "
2809435933ddSDimitry Andric                                 "supported (section '%s')\n",
2810435933ddSDimitry Andric                                 sect_name);
2811ac7ddfbfSEd Maste                             result.SetStatus(eReturnStatusFailed);
2812ac7ddfbfSEd Maste                             break;
2813435933ddSDimitry Andric                           } else {
2814435933ddSDimitry Andric                             if (target->GetSectionLoadList()
2815435933ddSDimitry Andric                                     .SetSectionLoadAddress(section_sp,
2816435933ddSDimitry Andric                                                            load_addr))
2817ac7ddfbfSEd Maste                               changed = true;
2818435933ddSDimitry Andric                             result.AppendMessageWithFormat(
2819435933ddSDimitry Andric                                 "section '%s' loaded at 0x%" PRIx64 "\n",
2820435933ddSDimitry Andric                                 sect_name, load_addr);
2821ac7ddfbfSEd Maste                           }
2822435933ddSDimitry Andric                         } else {
2823435933ddSDimitry Andric                           result.AppendErrorWithFormat("no section found that "
2824435933ddSDimitry Andric                                                        "matches the section "
2825435933ddSDimitry Andric                                                        "name '%s'\n",
2826435933ddSDimitry Andric                                                        sect_name);
2827ac7ddfbfSEd Maste                           result.SetStatus(eReturnStatusFailed);
2828ac7ddfbfSEd Maste                           break;
2829ac7ddfbfSEd Maste                         }
2830435933ddSDimitry Andric                       } else {
2831435933ddSDimitry Andric                         result.AppendErrorWithFormat(
2832435933ddSDimitry Andric                             "invalid load address string '%s'\n",
2833435933ddSDimitry Andric                             load_addr_cstr);
2834ac7ddfbfSEd Maste                         result.SetStatus(eReturnStatusFailed);
2835ac7ddfbfSEd Maste                         break;
2836ac7ddfbfSEd Maste                       }
2837435933ddSDimitry Andric                     } else {
2838ac7ddfbfSEd Maste                       if (sect_name)
2839435933ddSDimitry Andric                         result.AppendError("section names must be followed by "
2840435933ddSDimitry Andric                                            "a load address.\n");
2841ac7ddfbfSEd Maste                       else
2842435933ddSDimitry Andric                         result.AppendError("one or more section name + load "
2843435933ddSDimitry Andric                                            "address pair must be specified.\n");
2844ac7ddfbfSEd Maste                       result.SetStatus(eReturnStatusFailed);
2845ac7ddfbfSEd Maste                       break;
2846ac7ddfbfSEd Maste                     }
2847ac7ddfbfSEd Maste                   }
2848ac7ddfbfSEd Maste                 }
2849ac7ddfbfSEd Maste 
2850435933ddSDimitry Andric                 if (changed) {
2851ac7ddfbfSEd Maste                   target->ModulesDidLoad(matching_modules);
2852ac7ddfbfSEd Maste                   Process *process = m_exe_ctx.GetProcessPtr();
2853ac7ddfbfSEd Maste                   if (process)
2854ac7ddfbfSEd Maste                     process->Flush();
2855ac7ddfbfSEd Maste                 }
2856f678e45dSDimitry Andric                 if (load) {
28574ba319b5SDimitry Andric                   ProcessSP process = target->CalculateProcess();
28584ba319b5SDimitry Andric                   Address file_entry = objfile->GetEntryPointAddress();
28594ba319b5SDimitry Andric                   if (!process) {
28604ba319b5SDimitry Andric                     result.AppendError("No process");
28614ba319b5SDimitry Andric                     return false;
28624ba319b5SDimitry Andric                   }
28634ba319b5SDimitry Andric                   if (set_pc && !file_entry.IsValid()) {
28644ba319b5SDimitry Andric                     result.AppendError("No entry address in object file");
28654ba319b5SDimitry Andric                     return false;
28664ba319b5SDimitry Andric                   }
28674ba319b5SDimitry Andric                   std::vector<ObjectFile::LoadableData> loadables(
28684ba319b5SDimitry Andric                       objfile->GetLoadableData(*target));
28694ba319b5SDimitry Andric                   if (loadables.size() == 0) {
28704ba319b5SDimitry Andric                     result.AppendError("No loadable sections");
28714ba319b5SDimitry Andric                     return false;
28724ba319b5SDimitry Andric                   }
28734ba319b5SDimitry Andric                   Status error = process->WriteObjectFile(std::move(loadables));
2874f678e45dSDimitry Andric                   if (error.Fail()) {
2875f678e45dSDimitry Andric                     result.AppendError(error.AsCString());
2876f678e45dSDimitry Andric                     return false;
2877f678e45dSDimitry Andric                   }
28784ba319b5SDimitry Andric                   if (set_pc) {
28794ba319b5SDimitry Andric                     ThreadList &thread_list = process->GetThreadList();
28804ba319b5SDimitry Andric                     RegisterContextSP reg_context(
2881*b5893f02SDimitry Andric                         thread_list.GetSelectedThread()->GetRegisterContext());
2882*b5893f02SDimitry Andric                     addr_t file_entry_addr = file_entry.GetLoadAddress(target);
2883*b5893f02SDimitry Andric                     if (!reg_context->SetPC(file_entry_addr)) {
2884*b5893f02SDimitry Andric                       result.AppendErrorWithFormat("failed to set PC value to "
2885*b5893f02SDimitry Andric                                                    "0x%" PRIx64 "\n",
2886*b5893f02SDimitry Andric                                                    file_entry_addr);
2887*b5893f02SDimitry Andric                       result.SetStatus(eReturnStatusFailed);
2888*b5893f02SDimitry Andric                     }
28894ba319b5SDimitry Andric                   }
2890f678e45dSDimitry Andric                 }
2891435933ddSDimitry Andric               } else {
2892ac7ddfbfSEd Maste                 module->GetFileSpec().GetPath(path, sizeof(path));
2893435933ddSDimitry Andric                 result.AppendErrorWithFormat(
2894435933ddSDimitry Andric                     "no sections in object file '%s'\n", path);
2895ac7ddfbfSEd Maste                 result.SetStatus(eReturnStatusFailed);
2896ac7ddfbfSEd Maste               }
2897435933ddSDimitry Andric             } else {
2898ac7ddfbfSEd Maste               module->GetFileSpec().GetPath(path, sizeof(path));
2899435933ddSDimitry Andric               result.AppendErrorWithFormat("no object file for module '%s'\n",
2900435933ddSDimitry Andric                                            path);
2901ac7ddfbfSEd Maste               result.SetStatus(eReturnStatusFailed);
2902ac7ddfbfSEd Maste             }
2903435933ddSDimitry Andric           } else {
2904ac7ddfbfSEd Maste             FileSpec *module_spec_file = module_spec.GetFileSpecPtr();
2905435933ddSDimitry Andric             if (module_spec_file) {
2906ac7ddfbfSEd Maste               module_spec_file->GetPath(path, sizeof(path));
2907ac7ddfbfSEd Maste               result.AppendErrorWithFormat("invalid module '%s'.\n", path);
2908435933ddSDimitry Andric             } else
2909ac7ddfbfSEd Maste               result.AppendError("no module spec");
2910ac7ddfbfSEd Maste             result.SetStatus(eReturnStatusFailed);
2911ac7ddfbfSEd Maste           }
2912435933ddSDimitry Andric         } else {
2913ac7ddfbfSEd Maste           std::string uuid_str;
2914ac7ddfbfSEd Maste 
2915ac7ddfbfSEd Maste           if (module_spec.GetFileSpec())
2916ac7ddfbfSEd Maste             module_spec.GetFileSpec().GetPath(path, sizeof(path));
2917ac7ddfbfSEd Maste           else
2918ac7ddfbfSEd Maste             path[0] = '\0';
2919ac7ddfbfSEd Maste 
2920ac7ddfbfSEd Maste           if (module_spec.GetUUIDPtr())
2921ac7ddfbfSEd Maste             uuid_str = module_spec.GetUUID().GetAsString();
2922435933ddSDimitry Andric           if (num_matches > 1) {
2923435933ddSDimitry Andric             result.AppendErrorWithFormat(
2924435933ddSDimitry Andric                 "multiple modules match%s%s%s%s:\n", path[0] ? " file=" : "",
2925435933ddSDimitry Andric                 path, !uuid_str.empty() ? " uuid=" : "", uuid_str.c_str());
2926435933ddSDimitry Andric             for (size_t i = 0; i < num_matches; ++i) {
2927435933ddSDimitry Andric               if (matching_modules.GetModulePointerAtIndex(i)
2928435933ddSDimitry Andric                       ->GetFileSpec()
2929435933ddSDimitry Andric                       .GetPath(path, sizeof(path)))
2930ac7ddfbfSEd Maste                 result.AppendMessageWithFormat("%s\n", path);
2931ac7ddfbfSEd Maste             }
2932435933ddSDimitry Andric           } else {
2933435933ddSDimitry Andric             result.AppendErrorWithFormat(
2934435933ddSDimitry Andric                 "no modules were found  that match%s%s%s%s.\n",
2935435933ddSDimitry Andric                 path[0] ? " file=" : "", path,
2936435933ddSDimitry Andric                 !uuid_str.empty() ? " uuid=" : "", uuid_str.c_str());
2937ac7ddfbfSEd Maste           }
2938ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusFailed);
2939ac7ddfbfSEd Maste         }
2940435933ddSDimitry Andric       } else {
2941435933ddSDimitry Andric         result.AppendError("either the \"--file <module>\" or the \"--uuid "
2942435933ddSDimitry Andric                            "<uuid>\" option must be specified.\n");
2943ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
2944ac7ddfbfSEd Maste         return false;
2945ac7ddfbfSEd Maste       }
2946ac7ddfbfSEd Maste     }
2947ac7ddfbfSEd Maste     return result.Succeeded();
2948ac7ddfbfSEd Maste   }
2949ac7ddfbfSEd Maste 
2950ac7ddfbfSEd Maste   OptionGroupOptions m_option_group;
2951ac7ddfbfSEd Maste   OptionGroupUUID m_uuid_option_group;
29527aa51b79SEd Maste   OptionGroupString m_file_option;
2953f678e45dSDimitry Andric   OptionGroupBoolean m_load_option;
2954f678e45dSDimitry Andric   OptionGroupBoolean m_pc_option;
2955ac7ddfbfSEd Maste   OptionGroupUInt64 m_slide_option;
2956ac7ddfbfSEd Maste };
2957ac7ddfbfSEd Maste 
2958ac7ddfbfSEd Maste //----------------------------------------------------------------------
2959ac7ddfbfSEd Maste // List images with associated information
2960ac7ddfbfSEd Maste //----------------------------------------------------------------------
2961435933ddSDimitry Andric 
2962*b5893f02SDimitry Andric static constexpr OptionDefinition g_target_modules_list_options[] = {
2963435933ddSDimitry Andric     // clang-format off
2964*b5893f02SDimitry Andric   { LLDB_OPT_SET_1, false, "address",        'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Display the image at this address." },
2965*b5893f02SDimitry Andric   { LLDB_OPT_SET_1, false, "arch",           'A', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth,               "Display the architecture when listing images." },
2966*b5893f02SDimitry Andric   { LLDB_OPT_SET_1, false, "triple",         't', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth,               "Display the triple when listing images." },
2967*b5893f02SDimitry Andric   { LLDB_OPT_SET_1, false, "header",         'h', OptionParser::eNoArgument,       nullptr, {}, 0, eArgTypeNone,                "Display the image base address as a load address if debugging, a file address otherwise." },
2968*b5893f02SDimitry Andric   { LLDB_OPT_SET_1, false, "offset",         'o', OptionParser::eNoArgument,       nullptr, {}, 0, eArgTypeNone,                "Display the image load address offset from the base file address (the slide amount)." },
2969*b5893f02SDimitry Andric   { LLDB_OPT_SET_1, false, "uuid",           'u', OptionParser::eNoArgument,       nullptr, {}, 0, eArgTypeNone,                "Display the UUID when listing images." },
2970*b5893f02SDimitry Andric   { LLDB_OPT_SET_1, false, "fullpath",       'f', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth,               "Display the fullpath to the image object file." },
2971*b5893f02SDimitry Andric   { LLDB_OPT_SET_1, false, "directory",      'd', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth,               "Display the directory with optional width for the image object file." },
2972*b5893f02SDimitry Andric   { LLDB_OPT_SET_1, false, "basename",       'b', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth,               "Display the basename with optional width for the image object file." },
2973*b5893f02SDimitry Andric   { LLDB_OPT_SET_1, false, "symfile",        's', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth,               "Display the fullpath to the image symbol file with optional width." },
2974*b5893f02SDimitry Andric   { LLDB_OPT_SET_1, false, "symfile-unique", 'S', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth,               "Display the symbol file with optional width only if it is different from the executable object file." },
2975*b5893f02SDimitry Andric   { LLDB_OPT_SET_1, false, "mod-time",       'm', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth,               "Display the modification time with optional width of the module." },
2976*b5893f02SDimitry Andric   { LLDB_OPT_SET_1, false, "ref-count",      'r', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth,               "Display the reference count if the module is still in the shared module cache." },
2977*b5893f02SDimitry Andric   { LLDB_OPT_SET_1, false, "pointer",        'p', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeNone,                "Display the module pointer." },
2978*b5893f02SDimitry Andric   { LLDB_OPT_SET_1, false, "global",         'g', OptionParser::eNoArgument,       nullptr, {}, 0, eArgTypeNone,                "Display the modules from the global module list, not just the current target." }
2979435933ddSDimitry Andric     // clang-format on
2980435933ddSDimitry Andric };
2981435933ddSDimitry Andric 
2982435933ddSDimitry Andric class CommandObjectTargetModulesList : public CommandObjectParsed {
2983ac7ddfbfSEd Maste public:
2984435933ddSDimitry Andric   class CommandOptions : public Options {
2985ac7ddfbfSEd Maste   public:
CommandOptions()2986435933ddSDimitry Andric     CommandOptions()
2987435933ddSDimitry Andric         : Options(), m_format_array(), m_use_global_module_list(false),
2988435933ddSDimitry Andric           m_module_addr(LLDB_INVALID_ADDRESS) {}
2989ac7ddfbfSEd Maste 
29904bb0738eSEd Maste     ~CommandOptions() override = default;
2991ac7ddfbfSEd Maste 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)29925517e702SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2993435933ddSDimitry Andric                           ExecutionContext *execution_context) override {
29945517e702SDimitry Andric       Status error;
2995ac7ddfbfSEd Maste 
2996ac7ddfbfSEd Maste       const int short_option = m_getopt_table[option_idx].val;
2997435933ddSDimitry Andric       if (short_option == 'g') {
2998ac7ddfbfSEd Maste         m_use_global_module_list = true;
2999435933ddSDimitry Andric       } else if (short_option == 'a') {
30004ba319b5SDimitry Andric         m_module_addr = OptionArgParser::ToAddress(
30014ba319b5SDimitry Andric             execution_context, option_arg, LLDB_INVALID_ADDRESS, &error);
3002435933ddSDimitry Andric       } else {
3003ac7ddfbfSEd Maste         unsigned long width = 0;
3004435933ddSDimitry Andric         option_arg.getAsInteger(0, width);
3005ac7ddfbfSEd Maste         m_format_array.push_back(std::make_pair(short_option, width));
3006ac7ddfbfSEd Maste       }
3007ac7ddfbfSEd Maste       return error;
3008ac7ddfbfSEd Maste     }
3009ac7ddfbfSEd Maste 
OptionParsingStarting(ExecutionContext * execution_context)3010435933ddSDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
3011ac7ddfbfSEd Maste       m_format_array.clear();
3012ac7ddfbfSEd Maste       m_use_global_module_list = false;
3013ac7ddfbfSEd Maste       m_module_addr = LLDB_INVALID_ADDRESS;
3014ac7ddfbfSEd Maste     }
3015ac7ddfbfSEd Maste 
GetDefinitions()3016435933ddSDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
3017435933ddSDimitry Andric       return llvm::makeArrayRef(g_target_modules_list_options);
3018ac7ddfbfSEd Maste     }
3019ac7ddfbfSEd Maste 
3020ac7ddfbfSEd Maste     // Instance variables to hold the values for command options.
3021ac7ddfbfSEd Maste     typedef std::vector<std::pair<char, uint32_t>> FormatWidthCollection;
3022ac7ddfbfSEd Maste     FormatWidthCollection m_format_array;
3023ac7ddfbfSEd Maste     bool m_use_global_module_list;
3024ac7ddfbfSEd Maste     lldb::addr_t m_module_addr;
3025ac7ddfbfSEd Maste   };
3026ac7ddfbfSEd Maste 
CommandObjectTargetModulesList(CommandInterpreter & interpreter)3027435933ddSDimitry Andric   CommandObjectTargetModulesList(CommandInterpreter &interpreter)
3028435933ddSDimitry Andric       : CommandObjectParsed(
3029435933ddSDimitry Andric             interpreter, "target modules list",
3030ac7ddfbfSEd Maste             "List current executable and dependent shared library images.",
3031ac7ddfbfSEd Maste             "target modules list [<cmd-options>]"),
3032435933ddSDimitry Andric         m_options() {}
3033ac7ddfbfSEd Maste 
30344bb0738eSEd Maste   ~CommandObjectTargetModulesList() override = default;
3035ac7ddfbfSEd Maste 
GetOptions()3036435933ddSDimitry Andric   Options *GetOptions() override { return &m_options; }
3037ac7ddfbfSEd Maste 
3038ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)3039435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
3040ac7ddfbfSEd Maste     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
3041ac7ddfbfSEd Maste     const bool use_global_module_list = m_options.m_use_global_module_list;
3042435933ddSDimitry Andric     // Define a local module list here to ensure it lives longer than any
30434ba319b5SDimitry Andric     // "locker" object which might lock its contents below (through the
30444ba319b5SDimitry Andric     // "module_list_ptr" variable).
3045ac7ddfbfSEd Maste     ModuleList module_list;
3046435933ddSDimitry Andric     if (target == nullptr && !use_global_module_list) {
3047435933ddSDimitry Andric       result.AppendError("invalid target, create a debug target using the "
3048435933ddSDimitry Andric                          "'target create' command");
3049ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
3050ac7ddfbfSEd Maste       return false;
3051435933ddSDimitry Andric     } else {
3052435933ddSDimitry Andric       if (target) {
3053435933ddSDimitry Andric         uint32_t addr_byte_size =
3054435933ddSDimitry Andric             target->GetArchitecture().GetAddressByteSize();
3055ac7ddfbfSEd Maste         result.GetOutputStream().SetAddressByteSize(addr_byte_size);
3056ac7ddfbfSEd Maste         result.GetErrorStream().SetAddressByteSize(addr_byte_size);
3057ac7ddfbfSEd Maste       }
3058ac7ddfbfSEd Maste       // Dump all sections for all modules images
3059ac7ddfbfSEd Maste       Stream &strm = result.GetOutputStream();
3060ac7ddfbfSEd Maste 
3061435933ddSDimitry Andric       if (m_options.m_module_addr != LLDB_INVALID_ADDRESS) {
3062435933ddSDimitry Andric         if (target) {
3063ac7ddfbfSEd Maste           Address module_address;
3064435933ddSDimitry Andric           if (module_address.SetLoadAddress(m_options.m_module_addr, target)) {
3065ac7ddfbfSEd Maste             ModuleSP module_sp(module_address.GetModule());
3066435933ddSDimitry Andric             if (module_sp) {
3067ac7ddfbfSEd Maste               PrintModule(target, module_sp.get(), 0, strm);
3068ac7ddfbfSEd Maste               result.SetStatus(eReturnStatusSuccessFinishResult);
3069435933ddSDimitry Andric             } else {
3070435933ddSDimitry Andric               result.AppendErrorWithFormat(
3071435933ddSDimitry Andric                   "Couldn't find module matching address: 0x%" PRIx64 ".",
3072435933ddSDimitry Andric                   m_options.m_module_addr);
3073ac7ddfbfSEd Maste               result.SetStatus(eReturnStatusFailed);
3074ac7ddfbfSEd Maste             }
3075435933ddSDimitry Andric           } else {
3076435933ddSDimitry Andric             result.AppendErrorWithFormat(
3077435933ddSDimitry Andric                 "Couldn't find module containing address: 0x%" PRIx64 ".",
3078435933ddSDimitry Andric                 m_options.m_module_addr);
3079ac7ddfbfSEd Maste             result.SetStatus(eReturnStatusFailed);
3080ac7ddfbfSEd Maste           }
3081435933ddSDimitry Andric         } else {
3082435933ddSDimitry Andric           result.AppendError(
3083435933ddSDimitry Andric               "Can only look up modules by address with a valid target.");
3084ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusFailed);
3085ac7ddfbfSEd Maste         }
3086ac7ddfbfSEd Maste         return result.Succeeded();
3087ac7ddfbfSEd Maste       }
3088ac7ddfbfSEd Maste 
3089ac7ddfbfSEd Maste       size_t num_modules = 0;
30904bb0738eSEd Maste 
3091435933ddSDimitry Andric       // This locker will be locked on the mutex in module_list_ptr if it is
30924ba319b5SDimitry Andric       // non-nullptr. Otherwise it will lock the
30934ba319b5SDimitry Andric       // AllocationModuleCollectionMutex when accessing the global module list
30944ba319b5SDimitry Andric       // directly.
3095435933ddSDimitry Andric       std::unique_lock<std::recursive_mutex> guard(
3096435933ddSDimitry Andric           Module::GetAllocationModuleCollectionMutex(), std::defer_lock);
30974bb0738eSEd Maste 
30984bb0738eSEd Maste       const ModuleList *module_list_ptr = nullptr;
3099ac7ddfbfSEd Maste       const size_t argc = command.GetArgumentCount();
3100435933ddSDimitry Andric       if (argc == 0) {
3101435933ddSDimitry Andric         if (use_global_module_list) {
31024bb0738eSEd Maste           guard.lock();
3103ac7ddfbfSEd Maste           num_modules = Module::GetNumberAllocatedModules();
3104435933ddSDimitry Andric         } else {
3105ac7ddfbfSEd Maste           module_list_ptr = &target->GetImages();
3106ac7ddfbfSEd Maste         }
3107435933ddSDimitry Andric       } else {
3108435933ddSDimitry Andric         // TODO: Convert to entry based iteration.  Requires converting
3109435933ddSDimitry Andric         // FindModulesByName.
3110435933ddSDimitry Andric         for (size_t i = 0; i < argc; ++i) {
3111ac7ddfbfSEd Maste           // Dump specified images (by basename or fullpath)
3112ac7ddfbfSEd Maste           const char *arg_cstr = command.GetArgumentAtIndex(i);
3113435933ddSDimitry Andric           const size_t num_matches = FindModulesByName(
3114435933ddSDimitry Andric               target, arg_cstr, module_list, use_global_module_list);
3115435933ddSDimitry Andric           if (num_matches == 0) {
3116435933ddSDimitry Andric             if (argc == 1) {
3117435933ddSDimitry Andric               result.AppendErrorWithFormat("no modules found that match '%s'",
3118435933ddSDimitry Andric                                            arg_cstr);
3119ac7ddfbfSEd Maste               result.SetStatus(eReturnStatusFailed);
3120ac7ddfbfSEd Maste               return false;
3121ac7ddfbfSEd Maste             }
3122ac7ddfbfSEd Maste           }
3123ac7ddfbfSEd Maste         }
3124ac7ddfbfSEd Maste 
3125ac7ddfbfSEd Maste         module_list_ptr = &module_list;
3126ac7ddfbfSEd Maste       }
3127ac7ddfbfSEd Maste 
31284bb0738eSEd Maste       std::unique_lock<std::recursive_mutex> lock;
3129435933ddSDimitry Andric       if (module_list_ptr != nullptr) {
3130435933ddSDimitry Andric         lock =
3131435933ddSDimitry Andric             std::unique_lock<std::recursive_mutex>(module_list_ptr->GetMutex());
31324bb0738eSEd Maste 
3133ac7ddfbfSEd Maste         num_modules = module_list_ptr->GetSize();
3134ac7ddfbfSEd Maste       }
3135ac7ddfbfSEd Maste 
3136435933ddSDimitry Andric       if (num_modules > 0) {
3137435933ddSDimitry Andric         for (uint32_t image_idx = 0; image_idx < num_modules; ++image_idx) {
3138ac7ddfbfSEd Maste           ModuleSP module_sp;
3139ac7ddfbfSEd Maste           Module *module;
3140435933ddSDimitry Andric           if (module_list_ptr) {
3141ac7ddfbfSEd Maste             module_sp = module_list_ptr->GetModuleAtIndexUnlocked(image_idx);
3142ac7ddfbfSEd Maste             module = module_sp.get();
3143435933ddSDimitry Andric           } else {
3144ac7ddfbfSEd Maste             module = Module::GetAllocatedModuleAtIndex(image_idx);
3145ac7ddfbfSEd Maste             module_sp = module->shared_from_this();
3146ac7ddfbfSEd Maste           }
3147ac7ddfbfSEd Maste 
3148ac7ddfbfSEd Maste           const size_t indent = strm.Printf("[%3u] ", image_idx);
3149ac7ddfbfSEd Maste           PrintModule(target, module, indent, strm);
3150ac7ddfbfSEd Maste         }
3151ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusSuccessFinishResult);
3152435933ddSDimitry Andric       } else {
3153435933ddSDimitry Andric         if (argc) {
3154ac7ddfbfSEd Maste           if (use_global_module_list)
3155435933ddSDimitry Andric             result.AppendError(
3156435933ddSDimitry Andric                 "the global module list has no matching modules");
3157ac7ddfbfSEd Maste           else
3158ac7ddfbfSEd Maste             result.AppendError("the target has no matching modules");
3159435933ddSDimitry Andric         } else {
3160ac7ddfbfSEd Maste           if (use_global_module_list)
3161ac7ddfbfSEd Maste             result.AppendError("the global module list is empty");
3162ac7ddfbfSEd Maste           else
3163435933ddSDimitry Andric             result.AppendError(
3164435933ddSDimitry Andric                 "the target has no associated executable images");
3165ac7ddfbfSEd Maste         }
3166ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
3167ac7ddfbfSEd Maste         return false;
3168ac7ddfbfSEd Maste       }
3169ac7ddfbfSEd Maste     }
3170ac7ddfbfSEd Maste     return result.Succeeded();
3171ac7ddfbfSEd Maste   }
3172ac7ddfbfSEd Maste 
PrintModule(Target * target,Module * module,int indent,Stream & strm)3173435933ddSDimitry Andric   void PrintModule(Target *target, Module *module, int indent, Stream &strm) {
3174435933ddSDimitry Andric     if (module == nullptr) {
3175ac7ddfbfSEd Maste       strm.PutCString("Null module");
3176ac7ddfbfSEd Maste       return;
3177ac7ddfbfSEd Maste     }
3178ac7ddfbfSEd Maste 
3179ac7ddfbfSEd Maste     bool dump_object_name = false;
3180435933ddSDimitry Andric     if (m_options.m_format_array.empty()) {
3181ac7ddfbfSEd Maste       m_options.m_format_array.push_back(std::make_pair('u', 0));
3182ac7ddfbfSEd Maste       m_options.m_format_array.push_back(std::make_pair('h', 0));
3183ac7ddfbfSEd Maste       m_options.m_format_array.push_back(std::make_pair('f', 0));
3184ac7ddfbfSEd Maste       m_options.m_format_array.push_back(std::make_pair('S', 0));
3185ac7ddfbfSEd Maste     }
3186ac7ddfbfSEd Maste     const size_t num_entries = m_options.m_format_array.size();
3187ac7ddfbfSEd Maste     bool print_space = false;
3188435933ddSDimitry Andric     for (size_t i = 0; i < num_entries; ++i) {
3189ac7ddfbfSEd Maste       if (print_space)
3190ac7ddfbfSEd Maste         strm.PutChar(' ');
3191ac7ddfbfSEd Maste       print_space = true;
3192ac7ddfbfSEd Maste       const char format_char = m_options.m_format_array[i].first;
3193ac7ddfbfSEd Maste       uint32_t width = m_options.m_format_array[i].second;
3194435933ddSDimitry Andric       switch (format_char) {
3195ac7ddfbfSEd Maste       case 'A':
3196ac7ddfbfSEd Maste         DumpModuleArchitecture(strm, module, false, width);
3197ac7ddfbfSEd Maste         break;
3198ac7ddfbfSEd Maste 
3199ac7ddfbfSEd Maste       case 't':
3200ac7ddfbfSEd Maste         DumpModuleArchitecture(strm, module, true, width);
3201ac7ddfbfSEd Maste         break;
3202ac7ddfbfSEd Maste 
3203ac7ddfbfSEd Maste       case 'f':
3204ac7ddfbfSEd Maste         DumpFullpath(strm, &module->GetFileSpec(), width);
3205ac7ddfbfSEd Maste         dump_object_name = true;
3206ac7ddfbfSEd Maste         break;
3207ac7ddfbfSEd Maste 
3208ac7ddfbfSEd Maste       case 'd':
3209ac7ddfbfSEd Maste         DumpDirectory(strm, &module->GetFileSpec(), width);
3210ac7ddfbfSEd Maste         break;
3211ac7ddfbfSEd Maste 
3212ac7ddfbfSEd Maste       case 'b':
3213ac7ddfbfSEd Maste         DumpBasename(strm, &module->GetFileSpec(), width);
3214ac7ddfbfSEd Maste         dump_object_name = true;
3215ac7ddfbfSEd Maste         break;
3216ac7ddfbfSEd Maste 
3217ac7ddfbfSEd Maste       case 'h':
3218ac7ddfbfSEd Maste       case 'o':
3219ac7ddfbfSEd Maste         // Image header address
3220ac7ddfbfSEd Maste         {
3221435933ddSDimitry Andric           uint32_t addr_nibble_width =
3222435933ddSDimitry Andric               target ? (target->GetArchitecture().GetAddressByteSize() * 2)
3223435933ddSDimitry Andric                      : 16;
3224ac7ddfbfSEd Maste 
3225ac7ddfbfSEd Maste           ObjectFile *objfile = module->GetObjectFile();
3226435933ddSDimitry Andric           if (objfile) {
3227*b5893f02SDimitry Andric             Address base_addr(objfile->GetBaseAddress());
3228*b5893f02SDimitry Andric             if (base_addr.IsValid()) {
3229435933ddSDimitry Andric               if (target && !target->GetSectionLoadList().IsEmpty()) {
3230*b5893f02SDimitry Andric                 lldb::addr_t load_addr =
3231*b5893f02SDimitry Andric                     base_addr.GetLoadAddress(target);
3232*b5893f02SDimitry Andric                 if (load_addr == LLDB_INVALID_ADDRESS) {
3233*b5893f02SDimitry Andric                   base_addr.Dump(&strm, target,
3234435933ddSDimitry Andric                                    Address::DumpStyleModuleWithFileAddress,
3235435933ddSDimitry Andric                                    Address::DumpStyleFileAddress);
3236435933ddSDimitry Andric                 } else {
3237435933ddSDimitry Andric                   if (format_char == 'o') {
3238ac7ddfbfSEd Maste                     // Show the offset of slide for the image
3239435933ddSDimitry Andric                     strm.Printf(
3240435933ddSDimitry Andric                         "0x%*.*" PRIx64, addr_nibble_width, addr_nibble_width,
3241*b5893f02SDimitry Andric                         load_addr - base_addr.GetFileAddress());
3242435933ddSDimitry Andric                   } else {
3243ac7ddfbfSEd Maste                     // Show the load address of the image
3244435933ddSDimitry Andric                     strm.Printf("0x%*.*" PRIx64, addr_nibble_width,
3245*b5893f02SDimitry Andric                                 addr_nibble_width, load_addr);
3246ac7ddfbfSEd Maste                   }
3247ac7ddfbfSEd Maste                 }
3248ac7ddfbfSEd Maste                 break;
3249ac7ddfbfSEd Maste               }
3250435933ddSDimitry Andric               // The address was valid, but the image isn't loaded, output the
3251435933ddSDimitry Andric               // address in an appropriate format
3252*b5893f02SDimitry Andric               base_addr.Dump(&strm, target, Address::DumpStyleFileAddress);
3253ac7ddfbfSEd Maste               break;
3254ac7ddfbfSEd Maste             }
3255ac7ddfbfSEd Maste           }
3256ac7ddfbfSEd Maste           strm.Printf("%*s", addr_nibble_width + 2, "");
3257ac7ddfbfSEd Maste         }
3258ac7ddfbfSEd Maste         break;
32594bb0738eSEd Maste 
3260435933ddSDimitry Andric       case 'r': {
3261ac7ddfbfSEd Maste         size_t ref_count = 0;
3262ac7ddfbfSEd Maste         ModuleSP module_sp(module->shared_from_this());
3263435933ddSDimitry Andric         if (module_sp) {
3264ac7ddfbfSEd Maste           // Take one away to make sure we don't count our local "module_sp"
3265ac7ddfbfSEd Maste           ref_count = module_sp.use_count() - 1;
3266ac7ddfbfSEd Maste         }
3267ac7ddfbfSEd Maste         if (width)
32680127ef0fSEd Maste           strm.Printf("{%*" PRIu64 "}", width, (uint64_t)ref_count);
3269ac7ddfbfSEd Maste         else
32700127ef0fSEd Maste           strm.Printf("{%" PRIu64 "}", (uint64_t)ref_count);
3271435933ddSDimitry Andric       } break;
3272ac7ddfbfSEd Maste 
3273ac7ddfbfSEd Maste       case 's':
3274435933ddSDimitry Andric       case 'S': {
32751c3bbb01SEd Maste         const SymbolVendor *symbol_vendor = module->GetSymbolVendor();
3276435933ddSDimitry Andric         if (symbol_vendor) {
32771c3bbb01SEd Maste           const FileSpec symfile_spec = symbol_vendor->GetMainFileSpec();
3278435933ddSDimitry Andric           if (format_char == 'S') {
3279ac7ddfbfSEd Maste             // Dump symbol file only if different from module file
3280435933ddSDimitry Andric             if (!symfile_spec || symfile_spec == module->GetFileSpec()) {
3281ac7ddfbfSEd Maste               print_space = false;
3282ac7ddfbfSEd Maste               break;
3283ac7ddfbfSEd Maste             }
3284ac7ddfbfSEd Maste             // Add a newline and indent past the index
3285ac7ddfbfSEd Maste             strm.Printf("\n%*s", indent, "");
3286ac7ddfbfSEd Maste           }
32871c3bbb01SEd Maste           DumpFullpath(strm, &symfile_spec, width);
3288ac7ddfbfSEd Maste           dump_object_name = true;
3289ac7ddfbfSEd Maste           break;
3290ac7ddfbfSEd Maste         }
3291ac7ddfbfSEd Maste         strm.Printf("%.*s", width, "<NONE>");
3292435933ddSDimitry Andric       } break;
3293ac7ddfbfSEd Maste 
3294ac7ddfbfSEd Maste       case 'm':
3295acac075bSDimitry Andric         strm.Format("{0:%c}", llvm::fmt_align(module->GetModificationTime(),
3296acac075bSDimitry Andric                                               llvm::AlignStyle::Left, width));
3297ac7ddfbfSEd Maste         break;
3298ac7ddfbfSEd Maste 
3299ac7ddfbfSEd Maste       case 'p':
33000127ef0fSEd Maste         strm.Printf("%p", static_cast<void *>(module));
3301ac7ddfbfSEd Maste         break;
3302ac7ddfbfSEd Maste 
3303ac7ddfbfSEd Maste       case 'u':
3304ac7ddfbfSEd Maste         DumpModuleUUID(strm, module);
3305ac7ddfbfSEd Maste         break;
3306ac7ddfbfSEd Maste 
3307ac7ddfbfSEd Maste       default:
3308ac7ddfbfSEd Maste         break;
3309ac7ddfbfSEd Maste       }
3310ac7ddfbfSEd Maste     }
3311435933ddSDimitry Andric     if (dump_object_name) {
3312ac7ddfbfSEd Maste       const char *object_name = module->GetObjectName().GetCString();
3313ac7ddfbfSEd Maste       if (object_name)
3314ac7ddfbfSEd Maste         strm.Printf("(%s)", object_name);
3315ac7ddfbfSEd Maste     }
3316ac7ddfbfSEd Maste     strm.EOL();
3317ac7ddfbfSEd Maste   }
3318ac7ddfbfSEd Maste 
3319ac7ddfbfSEd Maste   CommandOptions m_options;
3320ac7ddfbfSEd Maste };
3321ac7ddfbfSEd Maste 
3322ac7ddfbfSEd Maste #pragma mark CommandObjectTargetModulesShowUnwind
3323ac7ddfbfSEd Maste 
3324ac7ddfbfSEd Maste //----------------------------------------------------------------------
3325ac7ddfbfSEd Maste // Lookup unwind information in images
3326ac7ddfbfSEd Maste //----------------------------------------------------------------------
3327ac7ddfbfSEd Maste 
3328*b5893f02SDimitry Andric static constexpr OptionDefinition g_target_modules_show_unwind_options[] = {
3329435933ddSDimitry Andric     // clang-format off
3330*b5893f02SDimitry Andric   { LLDB_OPT_SET_1, false, "name",    'n', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFunctionName,        "Show unwind instructions for a function or symbol name." },
3331*b5893f02SDimitry Andric   { LLDB_OPT_SET_2, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Show unwind instructions for a function or symbol containing an address" }
3332435933ddSDimitry Andric     // clang-format on
3333435933ddSDimitry Andric };
3334435933ddSDimitry Andric 
3335435933ddSDimitry Andric class CommandObjectTargetModulesShowUnwind : public CommandObjectParsed {
3336ac7ddfbfSEd Maste public:
3337435933ddSDimitry Andric   enum {
3338ac7ddfbfSEd Maste     eLookupTypeInvalid = -1,
3339ac7ddfbfSEd Maste     eLookupTypeAddress = 0,
3340ac7ddfbfSEd Maste     eLookupTypeSymbol,
3341ac7ddfbfSEd Maste     eLookupTypeFunction,
3342ac7ddfbfSEd Maste     eLookupTypeFunctionOrSymbol,
3343ac7ddfbfSEd Maste     kNumLookupTypes
3344ac7ddfbfSEd Maste   };
3345ac7ddfbfSEd Maste 
3346435933ddSDimitry Andric   class CommandOptions : public Options {
3347ac7ddfbfSEd Maste   public:
CommandOptions()3348435933ddSDimitry Andric     CommandOptions()
3349435933ddSDimitry Andric         : Options(), m_type(eLookupTypeInvalid), m_str(),
3350435933ddSDimitry Andric           m_addr(LLDB_INVALID_ADDRESS) {}
3351ac7ddfbfSEd Maste 
33524bb0738eSEd Maste     ~CommandOptions() override = default;
3353ac7ddfbfSEd Maste 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)33545517e702SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
3355435933ddSDimitry Andric                           ExecutionContext *execution_context) override {
33565517e702SDimitry Andric       Status error;
3357ac7ddfbfSEd Maste 
3358ac7ddfbfSEd Maste       const int short_option = m_getopt_table[option_idx].val;
3359ac7ddfbfSEd Maste 
3360435933ddSDimitry Andric       switch (short_option) {
3361435933ddSDimitry Andric       case 'a': {
336235617911SEd Maste         m_str = option_arg;
3363ac7ddfbfSEd Maste         m_type = eLookupTypeAddress;
33644ba319b5SDimitry Andric         m_addr = OptionArgParser::ToAddress(execution_context, option_arg,
3365435933ddSDimitry Andric                                             LLDB_INVALID_ADDRESS, &error);
3366ac7ddfbfSEd Maste         if (m_addr == LLDB_INVALID_ADDRESS)
3367435933ddSDimitry Andric           error.SetErrorStringWithFormat("invalid address string '%s'",
3368435933ddSDimitry Andric                                          option_arg.str().c_str());
3369ac7ddfbfSEd Maste         break;
3370ac7ddfbfSEd Maste       }
3371ac7ddfbfSEd Maste 
3372ac7ddfbfSEd Maste       case 'n':
3373ac7ddfbfSEd Maste         m_str = option_arg;
3374ac7ddfbfSEd Maste         m_type = eLookupTypeFunctionOrSymbol;
3375ac7ddfbfSEd Maste         break;
337635617911SEd Maste 
337735617911SEd Maste       default:
337835617911SEd Maste         error.SetErrorStringWithFormat("unrecognized option %c.", short_option);
337935617911SEd Maste         break;
3380ac7ddfbfSEd Maste       }
3381ac7ddfbfSEd Maste 
3382ac7ddfbfSEd Maste       return error;
3383ac7ddfbfSEd Maste     }
3384ac7ddfbfSEd Maste 
OptionParsingStarting(ExecutionContext * execution_context)3385435933ddSDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
3386ac7ddfbfSEd Maste       m_type = eLookupTypeInvalid;
3387ac7ddfbfSEd Maste       m_str.clear();
3388ac7ddfbfSEd Maste       m_addr = LLDB_INVALID_ADDRESS;
3389ac7ddfbfSEd Maste     }
3390ac7ddfbfSEd Maste 
GetDefinitions()3391435933ddSDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
3392435933ddSDimitry Andric       return llvm::makeArrayRef(g_target_modules_show_unwind_options);
3393ac7ddfbfSEd Maste     }
3394ac7ddfbfSEd Maste 
3395ac7ddfbfSEd Maste     // Instance variables to hold the values for command options.
3396ac7ddfbfSEd Maste 
3397ac7ddfbfSEd Maste     int m_type;        // Should be a eLookupTypeXXX enum after parsing options
3398ac7ddfbfSEd Maste     std::string m_str; // Holds name lookup
3399ac7ddfbfSEd Maste     lldb::addr_t m_addr; // Holds the address to lookup
3400ac7ddfbfSEd Maste   };
3401ac7ddfbfSEd Maste 
CommandObjectTargetModulesShowUnwind(CommandInterpreter & interpreter)3402435933ddSDimitry Andric   CommandObjectTargetModulesShowUnwind(CommandInterpreter &interpreter)
3403435933ddSDimitry Andric       : CommandObjectParsed(
3404435933ddSDimitry Andric             interpreter, "target modules show-unwind",
3405435933ddSDimitry Andric             "Show synthesized unwind instructions for a function.", nullptr,
3406435933ddSDimitry Andric             eCommandRequiresTarget | eCommandRequiresProcess |
3407435933ddSDimitry Andric                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused),
3408435933ddSDimitry Andric         m_options() {}
3409ac7ddfbfSEd Maste 
34104bb0738eSEd Maste   ~CommandObjectTargetModulesShowUnwind() override = default;
3411ac7ddfbfSEd Maste 
GetOptions()3412435933ddSDimitry Andric   Options *GetOptions() override { return &m_options; }
3413ac7ddfbfSEd Maste 
3414ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)3415435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
3416ac7ddfbfSEd Maste     Target *target = m_exe_ctx.GetTargetPtr();
3417ac7ddfbfSEd Maste     Process *process = m_exe_ctx.GetProcessPtr();
34184bb0738eSEd Maste     ABI *abi = nullptr;
3419ac7ddfbfSEd Maste     if (process)
3420ac7ddfbfSEd Maste       abi = process->GetABI().get();
3421ac7ddfbfSEd Maste 
3422435933ddSDimitry Andric     if (process == nullptr) {
3423435933ddSDimitry Andric       result.AppendError(
3424435933ddSDimitry Andric           "You must have a process running to use this command.");
3425ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
3426ac7ddfbfSEd Maste       return false;
3427ac7ddfbfSEd Maste     }
3428ac7ddfbfSEd Maste 
3429ac7ddfbfSEd Maste     ThreadList threads(process->GetThreadList());
3430435933ddSDimitry Andric     if (threads.GetSize() == 0) {
3431ac7ddfbfSEd Maste       result.AppendError("The process must be paused to use this command.");
3432ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
3433ac7ddfbfSEd Maste       return false;
3434ac7ddfbfSEd Maste     }
3435ac7ddfbfSEd Maste 
3436ac7ddfbfSEd Maste     ThreadSP thread(threads.GetThreadAtIndex(0));
3437435933ddSDimitry Andric     if (!thread) {
3438ac7ddfbfSEd Maste       result.AppendError("The process must be paused to use this command.");
3439ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
3440ac7ddfbfSEd Maste       return false;
3441ac7ddfbfSEd Maste     }
3442ac7ddfbfSEd Maste 
3443ac7ddfbfSEd Maste     SymbolContextList sc_list;
3444ac7ddfbfSEd Maste 
3445435933ddSDimitry Andric     if (m_options.m_type == eLookupTypeFunctionOrSymbol) {
3446ac7ddfbfSEd Maste       ConstString function_name(m_options.m_str.c_str());
3447435933ddSDimitry Andric       target->GetImages().FindFunctions(function_name, eFunctionNameTypeAuto,
3448435933ddSDimitry Andric                                         true, false, true, sc_list);
3449435933ddSDimitry Andric     } else if (m_options.m_type == eLookupTypeAddress && target) {
3450ac7ddfbfSEd Maste       Address addr;
3451435933ddSDimitry Andric       if (target->GetSectionLoadList().ResolveLoadAddress(m_options.m_addr,
3452435933ddSDimitry Andric                                                           addr)) {
3453ac7ddfbfSEd Maste         SymbolContext sc;
3454ac7ddfbfSEd Maste         ModuleSP module_sp(addr.GetModule());
3455435933ddSDimitry Andric         module_sp->ResolveSymbolContextForAddress(addr,
3456435933ddSDimitry Andric                                                   eSymbolContextEverything, sc);
3457435933ddSDimitry Andric         if (sc.function || sc.symbol) {
3458ac7ddfbfSEd Maste           sc_list.Append(sc);
3459ac7ddfbfSEd Maste         }
3460ac7ddfbfSEd Maste       }
3461435933ddSDimitry Andric     } else {
3462435933ddSDimitry Andric       result.AppendError(
3463435933ddSDimitry Andric           "address-expression or function name option must be specified.");
346435617911SEd Maste       result.SetStatus(eReturnStatusFailed);
346535617911SEd Maste       return false;
346635617911SEd Maste     }
3467ac7ddfbfSEd Maste 
3468ac7ddfbfSEd Maste     size_t num_matches = sc_list.GetSize();
3469435933ddSDimitry Andric     if (num_matches == 0) {
3470435933ddSDimitry Andric       result.AppendErrorWithFormat("no unwind data found that matches '%s'.",
3471435933ddSDimitry Andric                                    m_options.m_str.c_str());
347235617911SEd Maste       result.SetStatus(eReturnStatusFailed);
347335617911SEd Maste       return false;
347435617911SEd Maste     }
347535617911SEd Maste 
3476435933ddSDimitry Andric     for (uint32_t idx = 0; idx < num_matches; idx++) {
3477ac7ddfbfSEd Maste       SymbolContext sc;
3478ac7ddfbfSEd Maste       sc_list.GetContextAtIndex(idx, sc);
34794bb0738eSEd Maste       if (sc.symbol == nullptr && sc.function == nullptr)
3480ac7ddfbfSEd Maste         continue;
34814bb0738eSEd Maste       if (!sc.module_sp || sc.module_sp->GetObjectFile() == nullptr)
3482ac7ddfbfSEd Maste         continue;
3483ac7ddfbfSEd Maste       AddressRange range;
3484435933ddSDimitry Andric       if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0,
3485435933ddSDimitry Andric                               false, range))
3486ac7ddfbfSEd Maste         continue;
3487ac7ddfbfSEd Maste       if (!range.GetBaseAddress().IsValid())
3488ac7ddfbfSEd Maste         continue;
3489ac7ddfbfSEd Maste       ConstString funcname(sc.GetFunctionName());
3490ac7ddfbfSEd Maste       if (funcname.IsEmpty())
3491ac7ddfbfSEd Maste         continue;
3492ac7ddfbfSEd Maste       addr_t start_addr = range.GetBaseAddress().GetLoadAddress(target);
3493ac7ddfbfSEd Maste       if (abi)
3494ac7ddfbfSEd Maste         start_addr = abi->FixCodeAddress(start_addr);
3495ac7ddfbfSEd Maste 
3496435933ddSDimitry Andric       FuncUnwindersSP func_unwinders_sp(
3497435933ddSDimitry Andric           sc.module_sp->GetObjectFile()
3498435933ddSDimitry Andric               ->GetUnwindTable()
3499435933ddSDimitry Andric               .GetUncachedFuncUnwindersContainingAddress(start_addr, sc));
35004bb0738eSEd Maste       if (!func_unwinders_sp)
3501ac7ddfbfSEd Maste         continue;
3502ac7ddfbfSEd Maste 
3503435933ddSDimitry Andric       result.GetOutputStream().Printf(
3504435933ddSDimitry Andric           "UNWIND PLANS for %s`%s (start addr 0x%" PRIx64 ")\n\n",
3505435933ddSDimitry Andric           sc.module_sp->GetPlatformFileSpec().GetFilename().AsCString(),
3506435933ddSDimitry Andric           funcname.AsCString(), start_addr);
3507ac7ddfbfSEd Maste 
3508435933ddSDimitry Andric       UnwindPlanSP non_callsite_unwind_plan =
3509435933ddSDimitry Andric           func_unwinders_sp->GetUnwindPlanAtNonCallSite(*target, *thread, -1);
3510435933ddSDimitry Andric       if (non_callsite_unwind_plan) {
3511435933ddSDimitry Andric         result.GetOutputStream().Printf(
3512435933ddSDimitry Andric             "Asynchronous (not restricted to call-sites) UnwindPlan is '%s'\n",
3513435933ddSDimitry Andric             non_callsite_unwind_plan->GetSourceName().AsCString());
3514ac7ddfbfSEd Maste       }
3515435933ddSDimitry Andric       UnwindPlanSP callsite_unwind_plan =
3516435933ddSDimitry Andric           func_unwinders_sp->GetUnwindPlanAtCallSite(*target, -1);
3517435933ddSDimitry Andric       if (callsite_unwind_plan) {
3518435933ddSDimitry Andric         result.GetOutputStream().Printf(
3519435933ddSDimitry Andric             "Synchronous (restricted to call-sites) UnwindPlan is '%s'\n",
3520435933ddSDimitry Andric             callsite_unwind_plan->GetSourceName().AsCString());
3521ac7ddfbfSEd Maste       }
3522435933ddSDimitry Andric       UnwindPlanSP fast_unwind_plan =
3523435933ddSDimitry Andric           func_unwinders_sp->GetUnwindPlanFastUnwind(*target, *thread);
3524435933ddSDimitry Andric       if (fast_unwind_plan) {
3525435933ddSDimitry Andric         result.GetOutputStream().Printf(
3526435933ddSDimitry Andric             "Fast UnwindPlan is '%s'\n",
3527435933ddSDimitry Andric             fast_unwind_plan->GetSourceName().AsCString());
35287aa51b79SEd Maste       }
35297aa51b79SEd Maste 
35307aa51b79SEd Maste       result.GetOutputStream().Printf("\n");
35317aa51b79SEd Maste 
3532435933ddSDimitry Andric       UnwindPlanSP assembly_sp =
3533435933ddSDimitry Andric           func_unwinders_sp->GetAssemblyUnwindPlan(*target, *thread, 0);
3534435933ddSDimitry Andric       if (assembly_sp) {
3535435933ddSDimitry Andric         result.GetOutputStream().Printf(
3536435933ddSDimitry Andric             "Assembly language inspection UnwindPlan:\n");
3537435933ddSDimitry Andric         assembly_sp->Dump(result.GetOutputStream(), thread.get(),
3538435933ddSDimitry Andric                           LLDB_INVALID_ADDRESS);
35397aa51b79SEd Maste         result.GetOutputStream().Printf("\n");
35407aa51b79SEd Maste       }
35417aa51b79SEd Maste 
3542435933ddSDimitry Andric       UnwindPlanSP ehframe_sp =
3543435933ddSDimitry Andric           func_unwinders_sp->GetEHFrameUnwindPlan(*target, 0);
3544435933ddSDimitry Andric       if (ehframe_sp) {
35457aa51b79SEd Maste         result.GetOutputStream().Printf("eh_frame UnwindPlan:\n");
3546435933ddSDimitry Andric         ehframe_sp->Dump(result.GetOutputStream(), thread.get(),
3547435933ddSDimitry Andric                          LLDB_INVALID_ADDRESS);
35487aa51b79SEd Maste         result.GetOutputStream().Printf("\n");
35497aa51b79SEd Maste       }
35507aa51b79SEd Maste 
3551435933ddSDimitry Andric       UnwindPlanSP ehframe_augmented_sp =
3552435933ddSDimitry Andric           func_unwinders_sp->GetEHFrameAugmentedUnwindPlan(*target, *thread, 0);
3553435933ddSDimitry Andric       if (ehframe_augmented_sp) {
35547aa51b79SEd Maste         result.GetOutputStream().Printf("eh_frame augmented UnwindPlan:\n");
3555435933ddSDimitry Andric         ehframe_augmented_sp->Dump(result.GetOutputStream(), thread.get(),
3556435933ddSDimitry Andric                                    LLDB_INVALID_ADDRESS);
35577aa51b79SEd Maste         result.GetOutputStream().Printf("\n");
35587aa51b79SEd Maste       }
35597aa51b79SEd Maste 
3560a580b014SDimitry Andric       if (UnwindPlanSP plan_sp =
3561a580b014SDimitry Andric               func_unwinders_sp->GetDebugFrameUnwindPlan(*target, 0)) {
3562a580b014SDimitry Andric         result.GetOutputStream().Printf("debug_frame UnwindPlan:\n");
3563a580b014SDimitry Andric         plan_sp->Dump(result.GetOutputStream(), thread.get(),
3564a580b014SDimitry Andric                       LLDB_INVALID_ADDRESS);
3565a580b014SDimitry Andric         result.GetOutputStream().Printf("\n");
3566a580b014SDimitry Andric       }
3567a580b014SDimitry Andric 
3568a580b014SDimitry Andric       if (UnwindPlanSP plan_sp =
3569a580b014SDimitry Andric               func_unwinders_sp->GetDebugFrameAugmentedUnwindPlan(*target,
3570a580b014SDimitry Andric                                                                   *thread, 0)) {
3571a580b014SDimitry Andric         result.GetOutputStream().Printf("debug_frame augmented UnwindPlan:\n");
3572a580b014SDimitry Andric         plan_sp->Dump(result.GetOutputStream(), thread.get(),
3573a580b014SDimitry Andric                       LLDB_INVALID_ADDRESS);
3574a580b014SDimitry Andric         result.GetOutputStream().Printf("\n");
3575a580b014SDimitry Andric       }
3576a580b014SDimitry Andric 
3577435933ddSDimitry Andric       UnwindPlanSP arm_unwind_sp =
3578435933ddSDimitry Andric           func_unwinders_sp->GetArmUnwindUnwindPlan(*target, 0);
3579435933ddSDimitry Andric       if (arm_unwind_sp) {
35809f2f44ceSEd Maste         result.GetOutputStream().Printf("ARM.exidx unwind UnwindPlan:\n");
3581435933ddSDimitry Andric         arm_unwind_sp->Dump(result.GetOutputStream(), thread.get(),
3582435933ddSDimitry Andric                             LLDB_INVALID_ADDRESS);
35839f2f44ceSEd Maste         result.GetOutputStream().Printf("\n");
35849f2f44ceSEd Maste       }
35859f2f44ceSEd Maste 
3586435933ddSDimitry Andric       UnwindPlanSP compact_unwind_sp =
3587435933ddSDimitry Andric           func_unwinders_sp->GetCompactUnwindUnwindPlan(*target, 0);
3588435933ddSDimitry Andric       if (compact_unwind_sp) {
35897aa51b79SEd Maste         result.GetOutputStream().Printf("Compact unwind UnwindPlan:\n");
3590435933ddSDimitry Andric         compact_unwind_sp->Dump(result.GetOutputStream(), thread.get(),
3591435933ddSDimitry Andric                                 LLDB_INVALID_ADDRESS);
35927aa51b79SEd Maste         result.GetOutputStream().Printf("\n");
35937aa51b79SEd Maste       }
35947aa51b79SEd Maste 
3595435933ddSDimitry Andric       if (fast_unwind_plan) {
35967aa51b79SEd Maste         result.GetOutputStream().Printf("Fast UnwindPlan:\n");
3597435933ddSDimitry Andric         fast_unwind_plan->Dump(result.GetOutputStream(), thread.get(),
3598435933ddSDimitry Andric                                LLDB_INVALID_ADDRESS);
3599ac7ddfbfSEd Maste         result.GetOutputStream().Printf("\n");
3600ac7ddfbfSEd Maste       }
3601ac7ddfbfSEd Maste 
36027aa51b79SEd Maste       ABISP abi_sp = process->GetABI();
3603435933ddSDimitry Andric       if (abi_sp) {
36047aa51b79SEd Maste         UnwindPlan arch_default(lldb::eRegisterKindGeneric);
3605435933ddSDimitry Andric         if (abi_sp->CreateDefaultUnwindPlan(arch_default)) {
36067aa51b79SEd Maste           result.GetOutputStream().Printf("Arch default UnwindPlan:\n");
3607435933ddSDimitry Andric           arch_default.Dump(result.GetOutputStream(), thread.get(),
3608435933ddSDimitry Andric                             LLDB_INVALID_ADDRESS);
36097aa51b79SEd Maste           result.GetOutputStream().Printf("\n");
36107aa51b79SEd Maste         }
36117aa51b79SEd Maste 
36127aa51b79SEd Maste         UnwindPlan arch_entry(lldb::eRegisterKindGeneric);
3613435933ddSDimitry Andric         if (abi_sp->CreateFunctionEntryUnwindPlan(arch_entry)) {
3614435933ddSDimitry Andric           result.GetOutputStream().Printf(
3615435933ddSDimitry Andric               "Arch default at entry point UnwindPlan:\n");
3616435933ddSDimitry Andric           arch_entry.Dump(result.GetOutputStream(), thread.get(),
3617435933ddSDimitry Andric                           LLDB_INVALID_ADDRESS);
36187aa51b79SEd Maste           result.GetOutputStream().Printf("\n");
36197aa51b79SEd Maste         }
36207aa51b79SEd Maste       }
3621ac7ddfbfSEd Maste 
3622ac7ddfbfSEd Maste       result.GetOutputStream().Printf("\n");
3623ac7ddfbfSEd Maste     }
3624ac7ddfbfSEd Maste     return result.Succeeded();
3625ac7ddfbfSEd Maste   }
3626ac7ddfbfSEd Maste 
3627ac7ddfbfSEd Maste   CommandOptions m_options;
3628ac7ddfbfSEd Maste };
3629ac7ddfbfSEd Maste 
3630ac7ddfbfSEd Maste //----------------------------------------------------------------------
3631ac7ddfbfSEd Maste // Lookup information in images
3632ac7ddfbfSEd Maste //----------------------------------------------------------------------
3633435933ddSDimitry Andric 
3634*b5893f02SDimitry Andric static constexpr OptionDefinition g_target_modules_lookup_options[] = {
3635435933ddSDimitry Andric     // clang-format off
3636*b5893f02SDimitry Andric   { LLDB_OPT_SET_1,                                  true,  "address",    'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Lookup an address in one or more target modules." },
3637*b5893f02SDimitry Andric   { LLDB_OPT_SET_1,                                  false, "offset",     'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOffset,              "When looking up an address subtract <offset> from any addresses before doing the lookup." },
3638435933ddSDimitry Andric   /* FIXME: re-enable regex for types when the LookupTypeInModule actually uses the regex option: | LLDB_OPT_SET_6 */
3639*b5893f02SDimitry Andric   { LLDB_OPT_SET_2 | LLDB_OPT_SET_4 | LLDB_OPT_SET_5, false, "regex",      'r', OptionParser::eNoArgument,      nullptr, {}, 0, eArgTypeNone,                "The <name> argument for name lookups are regular expressions." },
3640*b5893f02SDimitry Andric   { LLDB_OPT_SET_2,                                  true,  "symbol",     's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeSymbol,              "Lookup a symbol by name in the symbol tables in one or more target modules." },
3641*b5893f02SDimitry Andric   { LLDB_OPT_SET_3,                                  true,  "file",       'f', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFilename,            "Lookup a file by fullpath or basename in one or more target modules." },
3642*b5893f02SDimitry Andric   { LLDB_OPT_SET_3,                                  false, "line",       'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum,             "Lookup a line number in a file (must be used in conjunction with --file)." },
3643*b5893f02SDimitry Andric   { LLDB_OPT_SET_FROM_TO(3,5),                       false, "no-inlines", 'i', OptionParser::eNoArgument,       nullptr, {}, 0, eArgTypeNone,                "Ignore inline entries (must be used in conjunction with --file or --function)." },
3644*b5893f02SDimitry Andric   { LLDB_OPT_SET_4,                                  true,  "function",   'F', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFunctionName,        "Lookup a function by name in the debug symbols in one or more target modules." },
3645*b5893f02SDimitry Andric   { LLDB_OPT_SET_5,                                  true,  "name",       'n', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFunctionOrSymbol,    "Lookup a function or symbol by name in one or more target modules." },
3646*b5893f02SDimitry Andric   { LLDB_OPT_SET_6,                                  true,  "type",       't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeName,                "Lookup a type by name in the debug symbols in one or more target modules." },
3647*b5893f02SDimitry Andric   { LLDB_OPT_SET_ALL,                                false, "verbose",    'v', OptionParser::eNoArgument,       nullptr, {}, 0, eArgTypeNone,                "Enable verbose lookup information." },
3648*b5893f02SDimitry Andric   { LLDB_OPT_SET_ALL,                                false, "all",        'A', OptionParser::eNoArgument,       nullptr, {}, 0, eArgTypeNone,                "Print all matches, not just the best match, if a best match is available." },
3649435933ddSDimitry Andric     // clang-format on
3650435933ddSDimitry Andric };
3651435933ddSDimitry Andric 
3652435933ddSDimitry Andric class CommandObjectTargetModulesLookup : public CommandObjectParsed {
3653ac7ddfbfSEd Maste public:
3654435933ddSDimitry Andric   enum {
3655ac7ddfbfSEd Maste     eLookupTypeInvalid = -1,
3656ac7ddfbfSEd Maste     eLookupTypeAddress = 0,
3657ac7ddfbfSEd Maste     eLookupTypeSymbol,
3658ac7ddfbfSEd Maste     eLookupTypeFileLine, // Line is optional
3659ac7ddfbfSEd Maste     eLookupTypeFunction,
3660ac7ddfbfSEd Maste     eLookupTypeFunctionOrSymbol,
3661ac7ddfbfSEd Maste     eLookupTypeType,
3662ac7ddfbfSEd Maste     kNumLookupTypes
3663ac7ddfbfSEd Maste   };
3664ac7ddfbfSEd Maste 
3665435933ddSDimitry Andric   class CommandOptions : public Options {
3666ac7ddfbfSEd Maste   public:
CommandOptions()3667435933ddSDimitry Andric     CommandOptions() : Options() { OptionParsingStarting(nullptr); }
3668ac7ddfbfSEd Maste 
36694bb0738eSEd Maste     ~CommandOptions() override = default;
3670ac7ddfbfSEd Maste 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)36715517e702SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
3672435933ddSDimitry Andric                           ExecutionContext *execution_context) override {
36735517e702SDimitry Andric       Status error;
3674ac7ddfbfSEd Maste 
3675ac7ddfbfSEd Maste       const int short_option = m_getopt_table[option_idx].val;
3676ac7ddfbfSEd Maste 
3677435933ddSDimitry Andric       switch (short_option) {
3678435933ddSDimitry Andric       case 'a': {
3679ac7ddfbfSEd Maste         m_type = eLookupTypeAddress;
36804ba319b5SDimitry Andric         m_addr = OptionArgParser::ToAddress(execution_context, option_arg,
3681435933ddSDimitry Andric                                             LLDB_INVALID_ADDRESS, &error);
3682435933ddSDimitry Andric       } break;
3683ac7ddfbfSEd Maste 
3684ac7ddfbfSEd Maste       case 'o':
3685435933ddSDimitry Andric         if (option_arg.getAsInteger(0, m_offset))
3686435933ddSDimitry Andric           error.SetErrorStringWithFormat("invalid offset string '%s'",
3687435933ddSDimitry Andric                                          option_arg.str().c_str());
3688ac7ddfbfSEd Maste         break;
3689ac7ddfbfSEd Maste 
3690ac7ddfbfSEd Maste       case 's':
3691ac7ddfbfSEd Maste         m_str = option_arg;
3692ac7ddfbfSEd Maste         m_type = eLookupTypeSymbol;
3693ac7ddfbfSEd Maste         break;
3694ac7ddfbfSEd Maste 
3695ac7ddfbfSEd Maste       case 'f':
3696*b5893f02SDimitry Andric         m_file.SetFile(option_arg, FileSpec::Style::native);
3697ac7ddfbfSEd Maste         m_type = eLookupTypeFileLine;
3698ac7ddfbfSEd Maste         break;
3699ac7ddfbfSEd Maste 
3700ac7ddfbfSEd Maste       case 'i':
3701ac7ddfbfSEd Maste         m_include_inlines = false;
3702ac7ddfbfSEd Maste         break;
3703ac7ddfbfSEd Maste 
3704ac7ddfbfSEd Maste       case 'l':
3705435933ddSDimitry Andric         if (option_arg.getAsInteger(0, m_line_number))
3706435933ddSDimitry Andric           error.SetErrorStringWithFormat("invalid line number string '%s'",
3707435933ddSDimitry Andric                                          option_arg.str().c_str());
3708ac7ddfbfSEd Maste         else if (m_line_number == 0)
3709ac7ddfbfSEd Maste           error.SetErrorString("zero is an invalid line number");
3710ac7ddfbfSEd Maste         m_type = eLookupTypeFileLine;
3711ac7ddfbfSEd Maste         break;
3712ac7ddfbfSEd Maste 
3713ac7ddfbfSEd Maste       case 'F':
3714ac7ddfbfSEd Maste         m_str = option_arg;
3715ac7ddfbfSEd Maste         m_type = eLookupTypeFunction;
3716ac7ddfbfSEd Maste         break;
3717ac7ddfbfSEd Maste 
3718ac7ddfbfSEd Maste       case 'n':
3719ac7ddfbfSEd Maste         m_str = option_arg;
3720ac7ddfbfSEd Maste         m_type = eLookupTypeFunctionOrSymbol;
3721ac7ddfbfSEd Maste         break;
3722ac7ddfbfSEd Maste 
3723ac7ddfbfSEd Maste       case 't':
3724ac7ddfbfSEd Maste         m_str = option_arg;
3725ac7ddfbfSEd Maste         m_type = eLookupTypeType;
3726ac7ddfbfSEd Maste         break;
3727ac7ddfbfSEd Maste 
3728ac7ddfbfSEd Maste       case 'v':
3729ac7ddfbfSEd Maste         m_verbose = 1;
3730ac7ddfbfSEd Maste         break;
3731ac7ddfbfSEd Maste 
3732ac7ddfbfSEd Maste       case 'A':
3733ac7ddfbfSEd Maste         m_print_all = true;
3734ac7ddfbfSEd Maste         break;
3735ac7ddfbfSEd Maste 
3736ac7ddfbfSEd Maste       case 'r':
3737ac7ddfbfSEd Maste         m_use_regex = true;
3738ac7ddfbfSEd Maste         break;
3739ac7ddfbfSEd Maste       }
3740ac7ddfbfSEd Maste 
3741ac7ddfbfSEd Maste       return error;
3742ac7ddfbfSEd Maste     }
3743ac7ddfbfSEd Maste 
OptionParsingStarting(ExecutionContext * execution_context)3744435933ddSDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
3745ac7ddfbfSEd Maste       m_type = eLookupTypeInvalid;
3746ac7ddfbfSEd Maste       m_str.clear();
3747ac7ddfbfSEd Maste       m_file.Clear();
3748ac7ddfbfSEd Maste       m_addr = LLDB_INVALID_ADDRESS;
3749ac7ddfbfSEd Maste       m_offset = 0;
3750ac7ddfbfSEd Maste       m_line_number = 0;
3751ac7ddfbfSEd Maste       m_use_regex = false;
3752ac7ddfbfSEd Maste       m_include_inlines = true;
3753ac7ddfbfSEd Maste       m_verbose = false;
3754ac7ddfbfSEd Maste       m_print_all = false;
3755ac7ddfbfSEd Maste     }
3756ac7ddfbfSEd Maste 
GetDefinitions()3757435933ddSDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
3758435933ddSDimitry Andric       return llvm::makeArrayRef(g_target_modules_lookup_options);
3759ac7ddfbfSEd Maste     }
3760ac7ddfbfSEd Maste 
3761ac7ddfbfSEd Maste     int m_type;        // Should be a eLookupTypeXXX enum after parsing options
3762ac7ddfbfSEd Maste     std::string m_str; // Holds name lookup
3763ac7ddfbfSEd Maste     FileSpec m_file;   // Files for file lookups
3764ac7ddfbfSEd Maste     lldb::addr_t m_addr; // Holds the address to lookup
3765435933ddSDimitry Andric     lldb::addr_t
3766435933ddSDimitry Andric         m_offset; // Subtract this offset from m_addr before doing lookups.
3767ac7ddfbfSEd Maste     uint32_t m_line_number; // Line number for file+line lookups
3768ac7ddfbfSEd Maste     bool m_use_regex;       // Name lookups in m_str are regular expressions.
3769435933ddSDimitry Andric     bool m_include_inlines; // Check for inline entries when looking up by
3770435933ddSDimitry Andric                             // file/line.
3771ac7ddfbfSEd Maste     bool m_verbose;         // Enable verbose lookup info
3772435933ddSDimitry Andric     bool m_print_all; // Print all matches, even in cases where there's a best
3773435933ddSDimitry Andric                       // match.
3774ac7ddfbfSEd Maste   };
3775ac7ddfbfSEd Maste 
CommandObjectTargetModulesLookup(CommandInterpreter & interpreter)3776435933ddSDimitry Andric   CommandObjectTargetModulesLookup(CommandInterpreter &interpreter)
3777435933ddSDimitry Andric       : CommandObjectParsed(interpreter, "target modules lookup",
3778435933ddSDimitry Andric                             "Look up information within executable and "
3779435933ddSDimitry Andric                             "dependent shared library images.",
3780435933ddSDimitry Andric                             nullptr, eCommandRequiresTarget),
3781435933ddSDimitry Andric         m_options() {
3782ac7ddfbfSEd Maste     CommandArgumentEntry arg;
3783ac7ddfbfSEd Maste     CommandArgumentData file_arg;
3784ac7ddfbfSEd Maste 
3785ac7ddfbfSEd Maste     // Define the first (and only) variant of this arg.
3786ac7ddfbfSEd Maste     file_arg.arg_type = eArgTypeFilename;
3787ac7ddfbfSEd Maste     file_arg.arg_repetition = eArgRepeatStar;
3788ac7ddfbfSEd Maste 
3789435933ddSDimitry Andric     // There is only one variant this argument could be; put it into the
3790435933ddSDimitry Andric     // argument entry.
3791ac7ddfbfSEd Maste     arg.push_back(file_arg);
3792ac7ddfbfSEd Maste 
3793ac7ddfbfSEd Maste     // Push the data for the first argument into the m_arguments vector.
3794ac7ddfbfSEd Maste     m_arguments.push_back(arg);
3795ac7ddfbfSEd Maste   }
3796ac7ddfbfSEd Maste 
37974bb0738eSEd Maste   ~CommandObjectTargetModulesLookup() override = default;
3798ac7ddfbfSEd Maste 
GetOptions()3799435933ddSDimitry Andric   Options *GetOptions() override { return &m_options; }
3800ac7ddfbfSEd Maste 
LookupHere(CommandInterpreter & interpreter,CommandReturnObject & result,bool & syntax_error)3801435933ddSDimitry Andric   bool LookupHere(CommandInterpreter &interpreter, CommandReturnObject &result,
3802435933ddSDimitry Andric                   bool &syntax_error) {
3803435933ddSDimitry Andric     switch (m_options.m_type) {
3804ac7ddfbfSEd Maste     case eLookupTypeAddress:
3805ac7ddfbfSEd Maste     case eLookupTypeFileLine:
3806ac7ddfbfSEd Maste     case eLookupTypeFunction:
3807ac7ddfbfSEd Maste     case eLookupTypeFunctionOrSymbol:
3808ac7ddfbfSEd Maste     case eLookupTypeSymbol:
3809ac7ddfbfSEd Maste     default:
3810ac7ddfbfSEd Maste       return false;
3811ac7ddfbfSEd Maste     case eLookupTypeType:
3812ac7ddfbfSEd Maste       break;
3813ac7ddfbfSEd Maste     }
3814ac7ddfbfSEd Maste 
3815ac7ddfbfSEd Maste     StackFrameSP frame = m_exe_ctx.GetFrameSP();
3816ac7ddfbfSEd Maste 
3817ac7ddfbfSEd Maste     if (!frame)
3818ac7ddfbfSEd Maste       return false;
3819ac7ddfbfSEd Maste 
3820ac7ddfbfSEd Maste     const SymbolContext &sym_ctx(frame->GetSymbolContext(eSymbolContextModule));
3821ac7ddfbfSEd Maste 
3822ac7ddfbfSEd Maste     if (!sym_ctx.module_sp)
3823ac7ddfbfSEd Maste       return false;
3824ac7ddfbfSEd Maste 
3825435933ddSDimitry Andric     switch (m_options.m_type) {
3826ac7ddfbfSEd Maste     default:
3827ac7ddfbfSEd Maste       return false;
3828ac7ddfbfSEd Maste     case eLookupTypeType:
3829435933ddSDimitry Andric       if (!m_options.m_str.empty()) {
3830*b5893f02SDimitry Andric         if (LookupTypeHere(m_interpreter, result.GetOutputStream(),
3831*b5893f02SDimitry Andric                            *sym_ctx.module_sp, m_options.m_str.c_str(),
3832*b5893f02SDimitry Andric                            m_options.m_use_regex)) {
3833ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusSuccessFinishResult);
3834ac7ddfbfSEd Maste           return true;
3835ac7ddfbfSEd Maste         }
3836ac7ddfbfSEd Maste       }
3837ac7ddfbfSEd Maste       break;
3838ac7ddfbfSEd Maste     }
3839ac7ddfbfSEd Maste 
3840ac7ddfbfSEd Maste     return true;
3841ac7ddfbfSEd Maste   }
3842ac7ddfbfSEd Maste 
LookupInModule(CommandInterpreter & interpreter,Module * module,CommandReturnObject & result,bool & syntax_error)3843435933ddSDimitry Andric   bool LookupInModule(CommandInterpreter &interpreter, Module *module,
3844435933ddSDimitry Andric                       CommandReturnObject &result, bool &syntax_error) {
3845435933ddSDimitry Andric     switch (m_options.m_type) {
3846ac7ddfbfSEd Maste     case eLookupTypeAddress:
3847435933ddSDimitry Andric       if (m_options.m_addr != LLDB_INVALID_ADDRESS) {
3848435933ddSDimitry Andric         if (LookupAddressInModule(
3849435933ddSDimitry Andric                 m_interpreter, result.GetOutputStream(), module,
3850435933ddSDimitry Andric                 eSymbolContextEverything |
3851435933ddSDimitry Andric                     (m_options.m_verbose
3852435933ddSDimitry Andric                          ? static_cast<int>(eSymbolContextVariable)
3853435933ddSDimitry Andric                          : 0),
3854435933ddSDimitry Andric                 m_options.m_addr, m_options.m_offset, m_options.m_verbose)) {
3855ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusSuccessFinishResult);
3856ac7ddfbfSEd Maste           return true;
3857ac7ddfbfSEd Maste         }
3858ac7ddfbfSEd Maste       }
3859ac7ddfbfSEd Maste       break;
3860ac7ddfbfSEd Maste 
3861ac7ddfbfSEd Maste     case eLookupTypeSymbol:
3862435933ddSDimitry Andric       if (!m_options.m_str.empty()) {
3863435933ddSDimitry Andric         if (LookupSymbolInModule(m_interpreter, result.GetOutputStream(),
3864435933ddSDimitry Andric                                  module, m_options.m_str.c_str(),
3865435933ddSDimitry Andric                                  m_options.m_use_regex, m_options.m_verbose)) {
3866ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusSuccessFinishResult);
3867ac7ddfbfSEd Maste           return true;
3868ac7ddfbfSEd Maste         }
3869ac7ddfbfSEd Maste       }
3870ac7ddfbfSEd Maste       break;
3871ac7ddfbfSEd Maste 
3872ac7ddfbfSEd Maste     case eLookupTypeFileLine:
3873435933ddSDimitry Andric       if (m_options.m_file) {
3874435933ddSDimitry Andric         if (LookupFileAndLineInModule(
3875435933ddSDimitry Andric                 m_interpreter, result.GetOutputStream(), module,
3876435933ddSDimitry Andric                 m_options.m_file, m_options.m_line_number,
3877435933ddSDimitry Andric                 m_options.m_include_inlines, m_options.m_verbose)) {
3878ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusSuccessFinishResult);
3879ac7ddfbfSEd Maste           return true;
3880ac7ddfbfSEd Maste         }
3881ac7ddfbfSEd Maste       }
3882ac7ddfbfSEd Maste       break;
3883ac7ddfbfSEd Maste 
3884ac7ddfbfSEd Maste     case eLookupTypeFunctionOrSymbol:
3885ac7ddfbfSEd Maste     case eLookupTypeFunction:
3886435933ddSDimitry Andric       if (!m_options.m_str.empty()) {
3887435933ddSDimitry Andric         if (LookupFunctionInModule(
3888435933ddSDimitry Andric                 m_interpreter, result.GetOutputStream(), module,
3889435933ddSDimitry Andric                 m_options.m_str.c_str(), m_options.m_use_regex,
3890ac7ddfbfSEd Maste                 m_options.m_include_inlines,
3891435933ddSDimitry Andric                 m_options.m_type ==
3892435933ddSDimitry Andric                     eLookupTypeFunctionOrSymbol, // include symbols
3893435933ddSDimitry Andric                 m_options.m_verbose)) {
3894ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusSuccessFinishResult);
3895ac7ddfbfSEd Maste           return true;
3896ac7ddfbfSEd Maste         }
3897ac7ddfbfSEd Maste       }
3898ac7ddfbfSEd Maste       break;
3899ac7ddfbfSEd Maste 
3900ac7ddfbfSEd Maste     case eLookupTypeType:
3901435933ddSDimitry Andric       if (!m_options.m_str.empty()) {
3902435933ddSDimitry Andric         if (LookupTypeInModule(m_interpreter, result.GetOutputStream(), module,
3903ac7ddfbfSEd Maste                                m_options.m_str.c_str(),
3904435933ddSDimitry Andric                                m_options.m_use_regex)) {
3905ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusSuccessFinishResult);
3906ac7ddfbfSEd Maste           return true;
3907ac7ddfbfSEd Maste         }
3908ac7ddfbfSEd Maste       }
3909ac7ddfbfSEd Maste       break;
3910ac7ddfbfSEd Maste 
3911ac7ddfbfSEd Maste     default:
3912435933ddSDimitry Andric       m_options.GenerateOptionUsage(
3913435933ddSDimitry Andric           result.GetErrorStream(), this,
3914435933ddSDimitry Andric           GetCommandInterpreter().GetDebugger().GetTerminalWidth());
3915ac7ddfbfSEd Maste       syntax_error = true;
3916ac7ddfbfSEd Maste       break;
3917ac7ddfbfSEd Maste     }
3918ac7ddfbfSEd Maste 
3919ac7ddfbfSEd Maste     result.SetStatus(eReturnStatusFailed);
3920ac7ddfbfSEd Maste     return false;
3921ac7ddfbfSEd Maste   }
3922ac7ddfbfSEd Maste 
3923ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)3924435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
3925ac7ddfbfSEd Maste     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
3926435933ddSDimitry Andric     if (target == nullptr) {
3927435933ddSDimitry Andric       result.AppendError("invalid target, create a debug target using the "
3928435933ddSDimitry Andric                          "'target create' command");
3929ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
3930ac7ddfbfSEd Maste       return false;
3931435933ddSDimitry Andric     } else {
3932ac7ddfbfSEd Maste       bool syntax_error = false;
3933ac7ddfbfSEd Maste       uint32_t i;
3934ac7ddfbfSEd Maste       uint32_t num_successful_lookups = 0;
3935ac7ddfbfSEd Maste       uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
3936ac7ddfbfSEd Maste       result.GetOutputStream().SetAddressByteSize(addr_byte_size);
3937ac7ddfbfSEd Maste       result.GetErrorStream().SetAddressByteSize(addr_byte_size);
3938ac7ddfbfSEd Maste       // Dump all sections for all modules images
3939ac7ddfbfSEd Maste 
3940435933ddSDimitry Andric       if (command.GetArgumentCount() == 0) {
3941ac7ddfbfSEd Maste         ModuleSP current_module;
3942ac7ddfbfSEd Maste 
39434ba319b5SDimitry Andric         // Where it is possible to look in the current symbol context first,
39444ba319b5SDimitry Andric         // try that.  If this search was successful and --all was not passed,
39454ba319b5SDimitry Andric         // don't print anything else.
3946435933ddSDimitry Andric         if (LookupHere(m_interpreter, result, syntax_error)) {
3947ac7ddfbfSEd Maste           result.GetOutputStream().EOL();
3948ac7ddfbfSEd Maste           num_successful_lookups++;
3949435933ddSDimitry Andric           if (!m_options.m_print_all) {
3950ac7ddfbfSEd Maste             result.SetStatus(eReturnStatusSuccessFinishResult);
3951ac7ddfbfSEd Maste             return result.Succeeded();
3952ac7ddfbfSEd Maste           }
3953ac7ddfbfSEd Maste         }
3954ac7ddfbfSEd Maste 
3955ac7ddfbfSEd Maste         // Dump all sections for all other modules
3956ac7ddfbfSEd Maste 
3957ac7ddfbfSEd Maste         const ModuleList &target_modules = target->GetImages();
39584bb0738eSEd Maste         std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
3959ac7ddfbfSEd Maste         const size_t num_modules = target_modules.GetSize();
3960435933ddSDimitry Andric         if (num_modules > 0) {
3961435933ddSDimitry Andric           for (i = 0; i < num_modules && !syntax_error; ++i) {
3962435933ddSDimitry Andric             Module *module_pointer =
3963435933ddSDimitry Andric                 target_modules.GetModulePointerAtIndexUnlocked(i);
3964ac7ddfbfSEd Maste 
3965ac7ddfbfSEd Maste             if (module_pointer != current_module.get() &&
3966435933ddSDimitry Andric                 LookupInModule(
3967435933ddSDimitry Andric                     m_interpreter,
3968435933ddSDimitry Andric                     target_modules.GetModulePointerAtIndexUnlocked(i), result,
3969435933ddSDimitry Andric                     syntax_error)) {
3970ac7ddfbfSEd Maste               result.GetOutputStream().EOL();
3971ac7ddfbfSEd Maste               num_successful_lookups++;
3972ac7ddfbfSEd Maste             }
3973ac7ddfbfSEd Maste           }
3974435933ddSDimitry Andric         } else {
3975ac7ddfbfSEd Maste           result.AppendError("the target has no associated executable images");
3976ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusFailed);
3977ac7ddfbfSEd Maste           return false;
3978ac7ddfbfSEd Maste         }
3979435933ddSDimitry Andric       } else {
3980ac7ddfbfSEd Maste         // Dump specified images (by basename or fullpath)
3981ac7ddfbfSEd Maste         const char *arg_cstr;
3982435933ddSDimitry Andric         for (i = 0; (arg_cstr = command.GetArgumentAtIndex(i)) != nullptr &&
3983435933ddSDimitry Andric                     !syntax_error;
3984435933ddSDimitry Andric              ++i) {
3985ac7ddfbfSEd Maste           ModuleList module_list;
3986435933ddSDimitry Andric           const size_t num_matches =
3987435933ddSDimitry Andric               FindModulesByName(target, arg_cstr, module_list, false);
3988435933ddSDimitry Andric           if (num_matches > 0) {
3989435933ddSDimitry Andric             for (size_t j = 0; j < num_matches; ++j) {
3990ac7ddfbfSEd Maste               Module *module = module_list.GetModulePointerAtIndex(j);
3991435933ddSDimitry Andric               if (module) {
3992435933ddSDimitry Andric                 if (LookupInModule(m_interpreter, module, result,
3993435933ddSDimitry Andric                                    syntax_error)) {
3994ac7ddfbfSEd Maste                   result.GetOutputStream().EOL();
3995ac7ddfbfSEd Maste                   num_successful_lookups++;
3996ac7ddfbfSEd Maste                 }
3997ac7ddfbfSEd Maste               }
3998ac7ddfbfSEd Maste             }
3999435933ddSDimitry Andric           } else
4000435933ddSDimitry Andric             result.AppendWarningWithFormat(
4001435933ddSDimitry Andric                 "Unable to find an image that matches '%s'.\n", arg_cstr);
4002ac7ddfbfSEd Maste         }
4003ac7ddfbfSEd Maste       }
4004ac7ddfbfSEd Maste 
4005ac7ddfbfSEd Maste       if (num_successful_lookups > 0)
4006ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusSuccessFinishResult);
4007ac7ddfbfSEd Maste       else
4008ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
4009ac7ddfbfSEd Maste     }
4010ac7ddfbfSEd Maste     return result.Succeeded();
4011ac7ddfbfSEd Maste   }
4012ac7ddfbfSEd Maste 
4013ac7ddfbfSEd Maste   CommandOptions m_options;
4014ac7ddfbfSEd Maste };
4015ac7ddfbfSEd Maste 
4016ac7ddfbfSEd Maste #pragma mark CommandObjectMultiwordImageSearchPaths
4017ac7ddfbfSEd Maste 
4018ac7ddfbfSEd Maste //-------------------------------------------------------------------------
4019ac7ddfbfSEd Maste // CommandObjectMultiwordImageSearchPaths
4020ac7ddfbfSEd Maste //-------------------------------------------------------------------------
4021ac7ddfbfSEd Maste 
4022435933ddSDimitry Andric class CommandObjectTargetModulesImageSearchPaths
4023435933ddSDimitry Andric     : public CommandObjectMultiword {
4024ac7ddfbfSEd Maste public:
CommandObjectTargetModulesImageSearchPaths(CommandInterpreter & interpreter)40254bb0738eSEd Maste   CommandObjectTargetModulesImageSearchPaths(CommandInterpreter &interpreter)
4026435933ddSDimitry Andric       : CommandObjectMultiword(
4027435933ddSDimitry Andric             interpreter, "target modules search-paths",
40284bb0738eSEd Maste             "Commands for managing module search paths for a target.",
4029435933ddSDimitry Andric             "target modules search-paths <subcommand> [<subcommand-options>]") {
4030435933ddSDimitry Andric     LoadSubCommand(
4031435933ddSDimitry Andric         "add", CommandObjectSP(
4032435933ddSDimitry Andric                    new CommandObjectTargetModulesSearchPathsAdd(interpreter)));
4033435933ddSDimitry Andric     LoadSubCommand(
4034435933ddSDimitry Andric         "clear", CommandObjectSP(new CommandObjectTargetModulesSearchPathsClear(
4035435933ddSDimitry Andric                      interpreter)));
4036435933ddSDimitry Andric     LoadSubCommand(
4037435933ddSDimitry Andric         "insert",
4038435933ddSDimitry Andric         CommandObjectSP(
4039435933ddSDimitry Andric             new CommandObjectTargetModulesSearchPathsInsert(interpreter)));
4040435933ddSDimitry Andric     LoadSubCommand(
4041435933ddSDimitry Andric         "list", CommandObjectSP(new CommandObjectTargetModulesSearchPathsList(
4042435933ddSDimitry Andric                     interpreter)));
4043435933ddSDimitry Andric     LoadSubCommand(
4044435933ddSDimitry Andric         "query", CommandObjectSP(new CommandObjectTargetModulesSearchPathsQuery(
4045435933ddSDimitry Andric                      interpreter)));
4046ac7ddfbfSEd Maste   }
4047ac7ddfbfSEd Maste 
40484bb0738eSEd Maste   ~CommandObjectTargetModulesImageSearchPaths() override = default;
4049ac7ddfbfSEd Maste };
4050ac7ddfbfSEd Maste 
4051ac7ddfbfSEd Maste #pragma mark CommandObjectTargetModules
4052ac7ddfbfSEd Maste 
4053ac7ddfbfSEd Maste //-------------------------------------------------------------------------
4054ac7ddfbfSEd Maste // CommandObjectTargetModules
4055ac7ddfbfSEd Maste //-------------------------------------------------------------------------
4056ac7ddfbfSEd Maste 
4057435933ddSDimitry Andric class CommandObjectTargetModules : public CommandObjectMultiword {
4058ac7ddfbfSEd Maste public:
4059ac7ddfbfSEd Maste   //------------------------------------------------------------------
4060ac7ddfbfSEd Maste   // Constructors and Destructors
4061ac7ddfbfSEd Maste   //------------------------------------------------------------------
CommandObjectTargetModules(CommandInterpreter & interpreter)40624bb0738eSEd Maste   CommandObjectTargetModules(CommandInterpreter &interpreter)
40634bb0738eSEd Maste       : CommandObjectMultiword(interpreter, "target modules",
4064435933ddSDimitry Andric                                "Commands for accessing information for one or "
4065435933ddSDimitry Andric                                "more target modules.",
4066435933ddSDimitry Andric                                "target modules <sub-command> ...") {
4067435933ddSDimitry Andric     LoadSubCommand(
4068435933ddSDimitry Andric         "add", CommandObjectSP(new CommandObjectTargetModulesAdd(interpreter)));
4069435933ddSDimitry Andric     LoadSubCommand("load", CommandObjectSP(new CommandObjectTargetModulesLoad(
4070435933ddSDimitry Andric                                interpreter)));
4071435933ddSDimitry Andric     LoadSubCommand("dump", CommandObjectSP(new CommandObjectTargetModulesDump(
4072435933ddSDimitry Andric                                interpreter)));
4073435933ddSDimitry Andric     LoadSubCommand("list", CommandObjectSP(new CommandObjectTargetModulesList(
4074435933ddSDimitry Andric                                interpreter)));
4075435933ddSDimitry Andric     LoadSubCommand(
4076435933ddSDimitry Andric         "lookup",
4077435933ddSDimitry Andric         CommandObjectSP(new CommandObjectTargetModulesLookup(interpreter)));
4078435933ddSDimitry Andric     LoadSubCommand(
4079435933ddSDimitry Andric         "search-paths",
4080435933ddSDimitry Andric         CommandObjectSP(
4081435933ddSDimitry Andric             new CommandObjectTargetModulesImageSearchPaths(interpreter)));
4082435933ddSDimitry Andric     LoadSubCommand(
4083435933ddSDimitry Andric         "show-unwind",
4084435933ddSDimitry Andric         CommandObjectSP(new CommandObjectTargetModulesShowUnwind(interpreter)));
4085ac7ddfbfSEd Maste   }
40869f2f44ceSEd Maste 
40874bb0738eSEd Maste   ~CommandObjectTargetModules() override = default;
4088ac7ddfbfSEd Maste 
4089ac7ddfbfSEd Maste private:
4090ac7ddfbfSEd Maste   //------------------------------------------------------------------
4091ac7ddfbfSEd Maste   // For CommandObjectTargetModules only
4092ac7ddfbfSEd Maste   //------------------------------------------------------------------
4093ac7ddfbfSEd Maste   DISALLOW_COPY_AND_ASSIGN(CommandObjectTargetModules);
4094ac7ddfbfSEd Maste };
4095ac7ddfbfSEd Maste 
4096435933ddSDimitry Andric class CommandObjectTargetSymbolsAdd : public CommandObjectParsed {
4097ac7ddfbfSEd Maste public:
CommandObjectTargetSymbolsAdd(CommandInterpreter & interpreter)4098435933ddSDimitry Andric   CommandObjectTargetSymbolsAdd(CommandInterpreter &interpreter)
4099435933ddSDimitry Andric       : CommandObjectParsed(
4100435933ddSDimitry Andric             interpreter, "target symbols add",
4101435933ddSDimitry Andric             "Add a debug symbol file to one of the target's current modules by "
4102435933ddSDimitry Andric             "specifying a path to a debug symbols file, or using the options "
4103435933ddSDimitry Andric             "to specify a module to download symbols for.",
4104acac075bSDimitry Andric             "target symbols add <cmd-options> [<symfile>]",
4105acac075bSDimitry Andric             eCommandRequiresTarget),
4106435933ddSDimitry Andric         m_option_group(),
4107435933ddSDimitry Andric         m_file_option(
4108435933ddSDimitry Andric             LLDB_OPT_SET_1, false, "shlib", 's',
4109435933ddSDimitry Andric             CommandCompletions::eModuleCompletion, eArgTypeShlibName,
4110435933ddSDimitry Andric             "Fullpath or basename for module to find debug symbols for."),
4111435933ddSDimitry Andric         m_current_frame_option(
4112435933ddSDimitry Andric             LLDB_OPT_SET_2, false, "frame", 'F',
4113435933ddSDimitry Andric             "Locate the debug symbols the currently selected frame.", false,
4114435933ddSDimitry Andric             true)
4115ac7ddfbfSEd Maste 
4116ac7ddfbfSEd Maste   {
4117435933ddSDimitry Andric     m_option_group.Append(&m_uuid_option_group, LLDB_OPT_SET_ALL,
4118435933ddSDimitry Andric                           LLDB_OPT_SET_1);
4119ac7ddfbfSEd Maste     m_option_group.Append(&m_file_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
4120435933ddSDimitry Andric     m_option_group.Append(&m_current_frame_option, LLDB_OPT_SET_2,
4121435933ddSDimitry Andric                           LLDB_OPT_SET_2);
4122ac7ddfbfSEd Maste     m_option_group.Finalize();
4123ac7ddfbfSEd Maste   }
4124ac7ddfbfSEd Maste 
41254bb0738eSEd Maste   ~CommandObjectTargetSymbolsAdd() override = default;
4126ac7ddfbfSEd Maste 
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)41274ba319b5SDimitry Andric   int HandleArgumentCompletion(
41284ba319b5SDimitry Andric       CompletionRequest &request,
41294ba319b5SDimitry Andric       OptionElementVector &opt_element_vector) override {
4130435933ddSDimitry Andric     CommandCompletions::InvokeCommonCompletionCallbacks(
4131435933ddSDimitry Andric         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
41324ba319b5SDimitry Andric         request, nullptr);
41334ba319b5SDimitry Andric     return request.GetNumberOfMatches();
4134ac7ddfbfSEd Maste   }
4135ac7ddfbfSEd Maste 
GetOptions()4136435933ddSDimitry Andric   Options *GetOptions() override { return &m_option_group; }
4137ac7ddfbfSEd Maste 
4138ac7ddfbfSEd Maste protected:
AddModuleSymbols(Target * target,ModuleSpec & module_spec,bool & flush,CommandReturnObject & result)4139435933ddSDimitry Andric   bool AddModuleSymbols(Target *target, ModuleSpec &module_spec, bool &flush,
4140435933ddSDimitry Andric                         CommandReturnObject &result) {
4141ac7ddfbfSEd Maste     const FileSpec &symbol_fspec = module_spec.GetSymbolFileSpec();
4142435933ddSDimitry Andric     if (symbol_fspec) {
4143ac7ddfbfSEd Maste       char symfile_path[PATH_MAX];
4144ac7ddfbfSEd Maste       symbol_fspec.GetPath(symfile_path, sizeof(symfile_path));
4145ac7ddfbfSEd Maste 
4146435933ddSDimitry Andric       if (!module_spec.GetUUID().IsValid()) {
4147ac7ddfbfSEd Maste         if (!module_spec.GetFileSpec() && !module_spec.GetPlatformFileSpec())
4148ac7ddfbfSEd Maste           module_spec.GetFileSpec().GetFilename() = symbol_fspec.GetFilename();
4149ac7ddfbfSEd Maste       }
41504ba319b5SDimitry Andric       // We now have a module that represents a symbol file that can be used
41514ba319b5SDimitry Andric       // for a module that might exist in the current target, so we need to
41524ba319b5SDimitry Andric       // find that module in the target
4153ac7ddfbfSEd Maste       ModuleList matching_module_list;
4154ac7ddfbfSEd Maste 
4155ac7ddfbfSEd Maste       size_t num_matches = 0;
4156ac7ddfbfSEd Maste       // First extract all module specs from the symbol file
4157ac7ddfbfSEd Maste       lldb_private::ModuleSpecList symfile_module_specs;
4158435933ddSDimitry Andric       if (ObjectFile::GetModuleSpecifications(module_spec.GetSymbolFileSpec(),
4159435933ddSDimitry Andric                                               0, 0, symfile_module_specs)) {
4160ac7ddfbfSEd Maste         // Now extract the module spec that matches the target architecture
4161ac7ddfbfSEd Maste         ModuleSpec target_arch_module_spec;
4162ac7ddfbfSEd Maste         ModuleSpec symfile_module_spec;
4163ac7ddfbfSEd Maste         target_arch_module_spec.GetArchitecture() = target->GetArchitecture();
4164435933ddSDimitry Andric         if (symfile_module_specs.FindMatchingModuleSpec(target_arch_module_spec,
4165435933ddSDimitry Andric                                                         symfile_module_spec)) {
4166ac7ddfbfSEd Maste           // See if it has a UUID?
4167435933ddSDimitry Andric           if (symfile_module_spec.GetUUID().IsValid()) {
4168ac7ddfbfSEd Maste             // It has a UUID, look for this UUID in the target modules
4169ac7ddfbfSEd Maste             ModuleSpec symfile_uuid_module_spec;
4170ac7ddfbfSEd Maste             symfile_uuid_module_spec.GetUUID() = symfile_module_spec.GetUUID();
4171435933ddSDimitry Andric             num_matches = target->GetImages().FindModules(
4172435933ddSDimitry Andric                 symfile_uuid_module_spec, matching_module_list);
4173ac7ddfbfSEd Maste           }
4174ac7ddfbfSEd Maste         }
4175ac7ddfbfSEd Maste 
4176435933ddSDimitry Andric         if (num_matches == 0) {
4177435933ddSDimitry Andric           // No matches yet, iterate through the module specs to find a UUID
41784ba319b5SDimitry Andric           // value that we can match up to an image in our target
4179435933ddSDimitry Andric           const size_t num_symfile_module_specs =
4180435933ddSDimitry Andric               symfile_module_specs.GetSize();
4181435933ddSDimitry Andric           for (size_t i = 0; i < num_symfile_module_specs && num_matches == 0;
4182435933ddSDimitry Andric                ++i) {
4183435933ddSDimitry Andric             if (symfile_module_specs.GetModuleSpecAtIndex(
4184435933ddSDimitry Andric                     i, symfile_module_spec)) {
4185435933ddSDimitry Andric               if (symfile_module_spec.GetUUID().IsValid()) {
4186ac7ddfbfSEd Maste                 // It has a UUID, look for this UUID in the target modules
4187ac7ddfbfSEd Maste                 ModuleSpec symfile_uuid_module_spec;
4188435933ddSDimitry Andric                 symfile_uuid_module_spec.GetUUID() =
4189435933ddSDimitry Andric                     symfile_module_spec.GetUUID();
4190435933ddSDimitry Andric                 num_matches = target->GetImages().FindModules(
4191435933ddSDimitry Andric                     symfile_uuid_module_spec, matching_module_list);
4192ac7ddfbfSEd Maste               }
4193ac7ddfbfSEd Maste             }
4194ac7ddfbfSEd Maste           }
4195ac7ddfbfSEd Maste         }
4196ac7ddfbfSEd Maste       }
4197ac7ddfbfSEd Maste 
41984ba319b5SDimitry Andric       // Just try to match up the file by basename if we have no matches at
41994ba319b5SDimitry Andric       // this point
4200ac7ddfbfSEd Maste       if (num_matches == 0)
4201435933ddSDimitry Andric         num_matches =
4202435933ddSDimitry Andric             target->GetImages().FindModules(module_spec, matching_module_list);
4203ac7ddfbfSEd Maste 
4204435933ddSDimitry Andric       while (num_matches == 0) {
4205435933ddSDimitry Andric         ConstString filename_no_extension(
4206435933ddSDimitry Andric             module_spec.GetFileSpec().GetFileNameStrippingExtension());
4207ac7ddfbfSEd Maste         // Empty string returned, lets bail
4208ac7ddfbfSEd Maste         if (!filename_no_extension)
4209ac7ddfbfSEd Maste           break;
4210ac7ddfbfSEd Maste 
42114ba319b5SDimitry Andric         // Check if there was no extension to strip and the basename is the
42124ba319b5SDimitry Andric         // same
4213ac7ddfbfSEd Maste         if (filename_no_extension == module_spec.GetFileSpec().GetFilename())
4214ac7ddfbfSEd Maste           break;
4215ac7ddfbfSEd Maste 
4216ac7ddfbfSEd Maste         // Replace basename with one less extension
4217ac7ddfbfSEd Maste         module_spec.GetFileSpec().GetFilename() = filename_no_extension;
4218ac7ddfbfSEd Maste 
4219435933ddSDimitry Andric         num_matches =
4220435933ddSDimitry Andric             target->GetImages().FindModules(module_spec, matching_module_list);
4221ac7ddfbfSEd Maste       }
4222ac7ddfbfSEd Maste 
4223435933ddSDimitry Andric       if (num_matches > 1) {
4224435933ddSDimitry Andric         result.AppendErrorWithFormat("multiple modules match symbol file '%s', "
4225435933ddSDimitry Andric                                      "use the --uuid option to resolve the "
4226435933ddSDimitry Andric                                      "ambiguity.\n",
4227435933ddSDimitry Andric                                      symfile_path);
4228435933ddSDimitry Andric       } else if (num_matches == 1) {
4229ac7ddfbfSEd Maste         ModuleSP module_sp(matching_module_list.GetModuleAtIndex(0));
4230ac7ddfbfSEd Maste 
42314ba319b5SDimitry Andric         // The module has not yet created its symbol vendor, we can just give
42324ba319b5SDimitry Andric         // the existing target module the symfile path to use for when it
42334ba319b5SDimitry Andric         // decides to create it!
4234ac7ddfbfSEd Maste         module_sp->SetSymbolFileFileSpec(symbol_fspec);
4235ac7ddfbfSEd Maste 
4236435933ddSDimitry Andric         SymbolVendor *symbol_vendor =
4237435933ddSDimitry Andric             module_sp->GetSymbolVendor(true, &result.GetErrorStream());
4238435933ddSDimitry Andric         if (symbol_vendor) {
4239ac7ddfbfSEd Maste           SymbolFile *symbol_file = symbol_vendor->GetSymbolFile();
4240ac7ddfbfSEd Maste 
4241435933ddSDimitry Andric           if (symbol_file) {
4242ac7ddfbfSEd Maste             ObjectFile *object_file = symbol_file->GetObjectFile();
4243ac7ddfbfSEd Maste 
4244435933ddSDimitry Andric             if (object_file && object_file->GetFileSpec() == symbol_fspec) {
4245ac7ddfbfSEd Maste               // Provide feedback that the symfile has been successfully added.
4246ac7ddfbfSEd Maste               const FileSpec &module_fs = module_sp->GetFileSpec();
4247435933ddSDimitry Andric               result.AppendMessageWithFormat(
4248435933ddSDimitry Andric                   "symbol file '%s' has been added to '%s'\n", symfile_path,
4249ac7ddfbfSEd Maste                   module_fs.GetPath().c_str());
4250ac7ddfbfSEd Maste 
42514ba319b5SDimitry Andric               // Let clients know something changed in the module if it is
42524ba319b5SDimitry Andric               // currently loaded
4253ac7ddfbfSEd Maste               ModuleList module_list;
4254ac7ddfbfSEd Maste               module_list.Append(module_sp);
4255ac7ddfbfSEd Maste               target->SymbolsDidLoad(module_list);
4256ac7ddfbfSEd Maste 
4257ac7ddfbfSEd Maste               // Make sure we load any scripting resources that may be embedded
4258ac7ddfbfSEd Maste               // in the debug info files in case the platform supports that.
42595517e702SDimitry Andric               Status error;
4260ac7ddfbfSEd Maste               StreamString feedback_stream;
4261435933ddSDimitry Andric               module_sp->LoadScriptingResourceInTarget(target, error,
4262435933ddSDimitry Andric                                                        &feedback_stream);
4263ac7ddfbfSEd Maste               if (error.Fail() && error.AsCString())
4264435933ddSDimitry Andric                 result.AppendWarningWithFormat(
4265435933ddSDimitry Andric                     "unable to load scripting data for module %s - error "
4266435933ddSDimitry Andric                     "reported was %s",
4267435933ddSDimitry Andric                     module_sp->GetFileSpec()
4268435933ddSDimitry Andric                         .GetFileNameStrippingExtension()
4269435933ddSDimitry Andric                         .GetCString(),
4270ac7ddfbfSEd Maste                     error.AsCString());
4271ac7ddfbfSEd Maste               else if (feedback_stream.GetSize())
4272ac7ddfbfSEd Maste                 result.AppendWarningWithFormat("%s", feedback_stream.GetData());
4273ac7ddfbfSEd Maste 
4274ac7ddfbfSEd Maste               flush = true;
4275ac7ddfbfSEd Maste               result.SetStatus(eReturnStatusSuccessFinishResult);
4276ac7ddfbfSEd Maste               return true;
4277ac7ddfbfSEd Maste             }
4278ac7ddfbfSEd Maste           }
4279ac7ddfbfSEd Maste         }
4280ac7ddfbfSEd Maste         // Clear the symbol file spec if anything went wrong
4281ac7ddfbfSEd Maste         module_sp->SetSymbolFileFileSpec(FileSpec());
4282ac7ddfbfSEd Maste       }
4283ac7ddfbfSEd Maste 
4284f678e45dSDimitry Andric       namespace fs = llvm::sys::fs;
4285435933ddSDimitry Andric       if (module_spec.GetUUID().IsValid()) {
4286ac7ddfbfSEd Maste         StreamString ss_symfile_uuid;
4287ac7ddfbfSEd Maste         module_spec.GetUUID().Dump(&ss_symfile_uuid);
4288435933ddSDimitry Andric         result.AppendErrorWithFormat(
4289435933ddSDimitry Andric             "symbol file '%s' (%s) does not match any existing module%s\n",
4290435933ddSDimitry Andric             symfile_path, ss_symfile_uuid.GetData(),
4291f678e45dSDimitry Andric             !fs::is_regular_file(symbol_fspec.GetPath())
4292ac7ddfbfSEd Maste                 ? "\n       please specify the full path to the symbol file"
4293ac7ddfbfSEd Maste                 : "");
4294435933ddSDimitry Andric       } else {
4295435933ddSDimitry Andric         result.AppendErrorWithFormat(
4296435933ddSDimitry Andric             "symbol file '%s' does not match any existing module%s\n",
4297ac7ddfbfSEd Maste             symfile_path,
4298f678e45dSDimitry Andric             !fs::is_regular_file(symbol_fspec.GetPath())
4299ac7ddfbfSEd Maste                 ? "\n       please specify the full path to the symbol file"
4300ac7ddfbfSEd Maste                 : "");
4301ac7ddfbfSEd Maste       }
4302435933ddSDimitry Andric     } else {
4303435933ddSDimitry Andric       result.AppendError(
4304435933ddSDimitry Andric           "one or more executable image paths must be specified");
4305ac7ddfbfSEd Maste     }
4306ac7ddfbfSEd Maste     result.SetStatus(eReturnStatusFailed);
4307ac7ddfbfSEd Maste     return false;
4308ac7ddfbfSEd Maste   }
4309ac7ddfbfSEd Maste 
DoExecute(Args & args,CommandReturnObject & result)4310435933ddSDimitry Andric   bool DoExecute(Args &args, CommandReturnObject &result) override {
4311ac7ddfbfSEd Maste     Target *target = m_exe_ctx.GetTargetPtr();
4312ac7ddfbfSEd Maste     result.SetStatus(eReturnStatusFailed);
4313ac7ddfbfSEd Maste     bool flush = false;
4314ac7ddfbfSEd Maste     ModuleSpec module_spec;
4315435933ddSDimitry Andric     const bool uuid_option_set =
4316435933ddSDimitry Andric         m_uuid_option_group.GetOptionValue().OptionWasSet();
4317ac7ddfbfSEd Maste     const bool file_option_set = m_file_option.GetOptionValue().OptionWasSet();
4318435933ddSDimitry Andric     const bool frame_option_set =
4319435933ddSDimitry Andric         m_current_frame_option.GetOptionValue().OptionWasSet();
4320ac7ddfbfSEd Maste     const size_t argc = args.GetArgumentCount();
43214bb0738eSEd Maste 
4322435933ddSDimitry Andric     if (argc == 0) {
4323435933ddSDimitry Andric       if (uuid_option_set || file_option_set || frame_option_set) {
4324ac7ddfbfSEd Maste         bool success = false;
4325ac7ddfbfSEd Maste         bool error_set = false;
4326435933ddSDimitry Andric         if (frame_option_set) {
4327ac7ddfbfSEd Maste           Process *process = m_exe_ctx.GetProcessPtr();
4328435933ddSDimitry Andric           if (process) {
4329ac7ddfbfSEd Maste             const StateType process_state = process->GetState();
4330435933ddSDimitry Andric             if (StateIsStoppedState(process_state, true)) {
4331ac7ddfbfSEd Maste               StackFrame *frame = m_exe_ctx.GetFramePtr();
4332435933ddSDimitry Andric               if (frame) {
4333435933ddSDimitry Andric                 ModuleSP frame_module_sp(
4334435933ddSDimitry Andric                     frame->GetSymbolContext(eSymbolContextModule).module_sp);
4335435933ddSDimitry Andric                 if (frame_module_sp) {
4336*b5893f02SDimitry Andric                   if (FileSystem::Instance().Exists(
4337*b5893f02SDimitry Andric                           frame_module_sp->GetPlatformFileSpec())) {
4338435933ddSDimitry Andric                     module_spec.GetArchitecture() =
4339435933ddSDimitry Andric                         frame_module_sp->GetArchitecture();
4340435933ddSDimitry Andric                     module_spec.GetFileSpec() =
4341435933ddSDimitry Andric                         frame_module_sp->GetPlatformFileSpec();
4342ac7ddfbfSEd Maste                   }
4343ac7ddfbfSEd Maste                   module_spec.GetUUID() = frame_module_sp->GetUUID();
4344435933ddSDimitry Andric                   success = module_spec.GetUUID().IsValid() ||
4345435933ddSDimitry Andric                             module_spec.GetFileSpec();
4346435933ddSDimitry Andric                 } else {
4347ac7ddfbfSEd Maste                   result.AppendError("frame has no module");
4348ac7ddfbfSEd Maste                   error_set = true;
4349ac7ddfbfSEd Maste                 }
4350435933ddSDimitry Andric               } else {
4351ac7ddfbfSEd Maste                 result.AppendError("invalid current frame");
4352ac7ddfbfSEd Maste                 error_set = true;
4353ac7ddfbfSEd Maste               }
4354435933ddSDimitry Andric             } else {
4355435933ddSDimitry Andric               result.AppendErrorWithFormat("process is not stopped: %s",
4356435933ddSDimitry Andric                                            StateAsCString(process_state));
4357ac7ddfbfSEd Maste               error_set = true;
4358ac7ddfbfSEd Maste             }
4359435933ddSDimitry Andric           } else {
4360435933ddSDimitry Andric             result.AppendError(
4361435933ddSDimitry Andric                 "a process must exist in order to use the --frame option");
4362ac7ddfbfSEd Maste             error_set = true;
4363ac7ddfbfSEd Maste           }
4364435933ddSDimitry Andric         } else {
4365435933ddSDimitry Andric           if (uuid_option_set) {
4366435933ddSDimitry Andric             module_spec.GetUUID() =
4367435933ddSDimitry Andric                 m_uuid_option_group.GetOptionValue().GetCurrentValue();
4368ac7ddfbfSEd Maste             success |= module_spec.GetUUID().IsValid();
4369435933ddSDimitry Andric           } else if (file_option_set) {
4370435933ddSDimitry Andric             module_spec.GetFileSpec() =
4371435933ddSDimitry Andric                 m_file_option.GetOptionValue().GetCurrentValue();
4372435933ddSDimitry Andric             ModuleSP module_sp(
4373435933ddSDimitry Andric                 target->GetImages().FindFirstModule(module_spec));
4374435933ddSDimitry Andric             if (module_sp) {
4375ac7ddfbfSEd Maste               module_spec.GetFileSpec() = module_sp->GetFileSpec();
4376435933ddSDimitry Andric               module_spec.GetPlatformFileSpec() =
4377435933ddSDimitry Andric                   module_sp->GetPlatformFileSpec();
4378ac7ddfbfSEd Maste               module_spec.GetUUID() = module_sp->GetUUID();
4379ac7ddfbfSEd Maste               module_spec.GetArchitecture() = module_sp->GetArchitecture();
4380435933ddSDimitry Andric             } else {
4381ac7ddfbfSEd Maste               module_spec.GetArchitecture() = target->GetArchitecture();
4382ac7ddfbfSEd Maste             }
4383435933ddSDimitry Andric             success |= module_spec.GetUUID().IsValid() ||
4384*b5893f02SDimitry Andric                        FileSystem::Instance().Exists(module_spec.GetFileSpec());
4385ac7ddfbfSEd Maste           }
4386ac7ddfbfSEd Maste         }
4387ac7ddfbfSEd Maste 
4388435933ddSDimitry Andric         if (success) {
4389435933ddSDimitry Andric           if (Symbols::DownloadObjectAndSymbolFile(module_spec)) {
4390ac7ddfbfSEd Maste             if (module_spec.GetSymbolFileSpec())
4391ac7ddfbfSEd Maste               success = AddModuleSymbols(target, module_spec, flush, result);
4392ac7ddfbfSEd Maste           }
4393ac7ddfbfSEd Maste         }
4394ac7ddfbfSEd Maste 
4395435933ddSDimitry Andric         if (!success && !error_set) {
4396ac7ddfbfSEd Maste           StreamString error_strm;
4397435933ddSDimitry Andric           if (uuid_option_set) {
4398ac7ddfbfSEd Maste             error_strm.PutCString("unable to find debug symbols for UUID ");
4399ac7ddfbfSEd Maste             module_spec.GetUUID().Dump(&error_strm);
4400435933ddSDimitry Andric           } else if (file_option_set) {
4401435933ddSDimitry Andric             error_strm.PutCString(
4402435933ddSDimitry Andric                 "unable to find debug symbols for the executable file ");
4403ac7ddfbfSEd Maste             error_strm << module_spec.GetFileSpec();
4404435933ddSDimitry Andric           } else if (frame_option_set) {
4405435933ddSDimitry Andric             error_strm.PutCString(
4406435933ddSDimitry Andric                 "unable to find debug symbols for the current frame");
4407ac7ddfbfSEd Maste           }
4408435933ddSDimitry Andric           result.AppendError(error_strm.GetString());
4409ac7ddfbfSEd Maste         }
4410435933ddSDimitry Andric       } else {
4411435933ddSDimitry Andric         result.AppendError("one or more symbol file paths must be specified, "
4412435933ddSDimitry Andric                            "or options must be specified");
4413ac7ddfbfSEd Maste       }
4414435933ddSDimitry Andric     } else {
4415435933ddSDimitry Andric       if (uuid_option_set) {
4416435933ddSDimitry Andric         result.AppendError("specify either one or more paths to symbol files "
4417435933ddSDimitry Andric                            "or use the --uuid option without arguments");
4418435933ddSDimitry Andric       } else if (frame_option_set) {
4419435933ddSDimitry Andric         result.AppendError("specify either one or more paths to symbol files "
4420435933ddSDimitry Andric                            "or use the --frame option without arguments");
4421acac075bSDimitry Andric       } else if (file_option_set && argc > 1) {
4422acac075bSDimitry Andric         result.AppendError("specify at most one symbol file path when "
4423acac075bSDimitry Andric                            "--shlib option is set");
4424435933ddSDimitry Andric       } else {
4425ac7ddfbfSEd Maste         PlatformSP platform_sp(target->GetPlatform());
4426ac7ddfbfSEd Maste 
4427435933ddSDimitry Andric         for (auto &entry : args.entries()) {
4428435933ddSDimitry Andric           if (!entry.ref.empty()) {
4429*b5893f02SDimitry Andric             auto &symbol_file_spec = module_spec.GetSymbolFileSpec();
4430*b5893f02SDimitry Andric             symbol_file_spec.SetFile(entry.ref, FileSpec::Style::native);
4431*b5893f02SDimitry Andric             FileSystem::Instance().Resolve(symbol_file_spec);
4432acac075bSDimitry Andric             if (file_option_set) {
4433acac075bSDimitry Andric               module_spec.GetFileSpec() =
4434acac075bSDimitry Andric                   m_file_option.GetOptionValue().GetCurrentValue();
4435acac075bSDimitry Andric             }
4436435933ddSDimitry Andric             if (platform_sp) {
4437ac7ddfbfSEd Maste               FileSpec symfile_spec;
4438435933ddSDimitry Andric               if (platform_sp
4439435933ddSDimitry Andric                       ->ResolveSymbolFile(*target, module_spec, symfile_spec)
4440435933ddSDimitry Andric                       .Success())
4441ac7ddfbfSEd Maste                 module_spec.GetSymbolFileSpec() = symfile_spec;
4442ac7ddfbfSEd Maste             }
4443ac7ddfbfSEd Maste 
4444ac7ddfbfSEd Maste             ArchSpec arch;
4445*b5893f02SDimitry Andric             bool symfile_exists =
4446*b5893f02SDimitry Andric                 FileSystem::Instance().Exists(module_spec.GetSymbolFileSpec());
4447ac7ddfbfSEd Maste 
4448435933ddSDimitry Andric             if (symfile_exists) {
4449ac7ddfbfSEd Maste               if (!AddModuleSymbols(target, module_spec, flush, result))
4450ac7ddfbfSEd Maste                 break;
4451435933ddSDimitry Andric             } else {
4452435933ddSDimitry Andric               std::string resolved_symfile_path =
4453435933ddSDimitry Andric                   module_spec.GetSymbolFileSpec().GetPath();
4454435933ddSDimitry Andric               if (resolved_symfile_path != entry.ref) {
4455435933ddSDimitry Andric                 result.AppendErrorWithFormat(
4456435933ddSDimitry Andric                     "invalid module path '%s' with resolved path '%s'\n",
4457435933ddSDimitry Andric                     entry.c_str(), resolved_symfile_path.c_str());
4458ac7ddfbfSEd Maste                 break;
4459ac7ddfbfSEd Maste               }
4460435933ddSDimitry Andric               result.AppendErrorWithFormat("invalid module path '%s'\n",
4461435933ddSDimitry Andric                                            entry.c_str());
4462ac7ddfbfSEd Maste               break;
4463ac7ddfbfSEd Maste             }
4464ac7ddfbfSEd Maste           }
4465ac7ddfbfSEd Maste         }
4466ac7ddfbfSEd Maste       }
4467ac7ddfbfSEd Maste     }
4468ac7ddfbfSEd Maste 
4469435933ddSDimitry Andric     if (flush) {
4470ac7ddfbfSEd Maste       Process *process = m_exe_ctx.GetProcessPtr();
4471ac7ddfbfSEd Maste       if (process)
4472ac7ddfbfSEd Maste         process->Flush();
4473ac7ddfbfSEd Maste     }
4474ac7ddfbfSEd Maste     return result.Succeeded();
4475ac7ddfbfSEd Maste   }
4476ac7ddfbfSEd Maste 
4477ac7ddfbfSEd Maste   OptionGroupOptions m_option_group;
4478ac7ddfbfSEd Maste   OptionGroupUUID m_uuid_option_group;
4479ac7ddfbfSEd Maste   OptionGroupFile m_file_option;
4480ac7ddfbfSEd Maste   OptionGroupBoolean m_current_frame_option;
4481ac7ddfbfSEd Maste };
4482ac7ddfbfSEd Maste 
4483ac7ddfbfSEd Maste #pragma mark CommandObjectTargetSymbols
4484ac7ddfbfSEd Maste 
4485ac7ddfbfSEd Maste //-------------------------------------------------------------------------
4486ac7ddfbfSEd Maste // CommandObjectTargetSymbols
4487ac7ddfbfSEd Maste //-------------------------------------------------------------------------
4488ac7ddfbfSEd Maste 
4489435933ddSDimitry Andric class CommandObjectTargetSymbols : public CommandObjectMultiword {
4490ac7ddfbfSEd Maste public:
4491ac7ddfbfSEd Maste   //------------------------------------------------------------------
4492ac7ddfbfSEd Maste   // Constructors and Destructors
4493ac7ddfbfSEd Maste   //------------------------------------------------------------------
CommandObjectTargetSymbols(CommandInterpreter & interpreter)44944bb0738eSEd Maste   CommandObjectTargetSymbols(CommandInterpreter &interpreter)
4495435933ddSDimitry Andric       : CommandObjectMultiword(
4496435933ddSDimitry Andric             interpreter, "target symbols",
4497435933ddSDimitry Andric             "Commands for adding and managing debug symbol files.",
4498435933ddSDimitry Andric             "target symbols <sub-command> ...") {
4499435933ddSDimitry Andric     LoadSubCommand(
4500435933ddSDimitry Andric         "add", CommandObjectSP(new CommandObjectTargetSymbolsAdd(interpreter)));
4501ac7ddfbfSEd Maste   }
45029f2f44ceSEd Maste 
45034bb0738eSEd Maste   ~CommandObjectTargetSymbols() override = default;
4504ac7ddfbfSEd Maste 
4505ac7ddfbfSEd Maste private:
4506ac7ddfbfSEd Maste   //------------------------------------------------------------------
4507ac7ddfbfSEd Maste   // For CommandObjectTargetModules only
4508ac7ddfbfSEd Maste   //------------------------------------------------------------------
4509ac7ddfbfSEd Maste   DISALLOW_COPY_AND_ASSIGN(CommandObjectTargetSymbols);
4510ac7ddfbfSEd Maste };
4511ac7ddfbfSEd Maste 
4512ac7ddfbfSEd Maste #pragma mark CommandObjectTargetStopHookAdd
4513ac7ddfbfSEd Maste 
4514ac7ddfbfSEd Maste //-------------------------------------------------------------------------
4515ac7ddfbfSEd Maste // CommandObjectTargetStopHookAdd
4516ac7ddfbfSEd Maste //-------------------------------------------------------------------------
4517ac7ddfbfSEd Maste 
4518*b5893f02SDimitry Andric static constexpr OptionDefinition g_target_stop_hook_add_options[] = {
4519435933ddSDimitry Andric     // clang-format off
4520*b5893f02SDimitry Andric   { LLDB_OPT_SET_ALL, false, "one-liner",    'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOneLiner,                                         "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." },
4521*b5893f02SDimitry Andric   { LLDB_OPT_SET_ALL, false, "shlib",        's', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eModuleCompletion, eArgTypeShlibName,    "Set the module within which the stop-hook is to be run." },
4522*b5893f02SDimitry Andric   { LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadIndex,                                      "The stop hook is run only for the thread whose index matches this argument." },
4523*b5893f02SDimitry Andric   { LLDB_OPT_SET_ALL, false, "thread-id",    't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadID,                                         "The stop hook is run only for the thread whose TID matches this argument." },
4524*b5893f02SDimitry Andric   { LLDB_OPT_SET_ALL, false, "thread-name",  'T', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadName,                                       "The stop hook is run only for the thread whose thread name matches this argument." },
4525*b5893f02SDimitry Andric   { LLDB_OPT_SET_ALL, false, "queue-name",   'q', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeQueueName,                                        "The stop hook is run only for threads in the queue whose name is given by this argument." },
4526*b5893f02SDimitry Andric   { LLDB_OPT_SET_1,   false, "file",         'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the source file within which the stop-hook is to be run." },
4527*b5893f02SDimitry Andric   { LLDB_OPT_SET_1,   false, "start-line",   'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum,                                          "Set the start of the line range for which the stop-hook is to be run." },
4528*b5893f02SDimitry Andric   { LLDB_OPT_SET_1,   false, "end-line",     'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum,                                          "Set the end of the line range for which the stop-hook is to be run." },
4529*b5893f02SDimitry Andric   { LLDB_OPT_SET_2,   false, "classname",    'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeClassName,                                        "Specify the class within which the stop-hook is to be run." },
4530*b5893f02SDimitry Andric   { LLDB_OPT_SET_3,   false, "name",         'n', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the function name within which the stop hook will be run." },
4531435933ddSDimitry Andric     // clang-format on
4532435933ddSDimitry Andric };
4533435933ddSDimitry Andric 
4534435933ddSDimitry Andric class CommandObjectTargetStopHookAdd : public CommandObjectParsed,
4535435933ddSDimitry Andric                                        public IOHandlerDelegateMultiline {
4536ac7ddfbfSEd Maste public:
4537435933ddSDimitry Andric   class CommandOptions : public Options {
4538ac7ddfbfSEd Maste   public:
CommandOptions()4539435933ddSDimitry Andric     CommandOptions()
4540435933ddSDimitry Andric         : Options(), m_line_start(0), m_line_end(UINT_MAX),
4541ac7ddfbfSEd Maste           m_func_name_type_mask(eFunctionNameTypeAuto),
4542435933ddSDimitry Andric           m_sym_ctx_specified(false), m_thread_specified(false),
4543435933ddSDimitry Andric           m_use_one_liner(false), m_one_liner() {}
4544ac7ddfbfSEd Maste 
45454bb0738eSEd Maste     ~CommandOptions() override = default;
4546ac7ddfbfSEd Maste 
GetDefinitions()4547435933ddSDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
4548435933ddSDimitry Andric       return llvm::makeArrayRef(g_target_stop_hook_add_options);
4549ac7ddfbfSEd Maste     }
4550ac7ddfbfSEd Maste 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)45515517e702SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
4552435933ddSDimitry Andric                           ExecutionContext *execution_context) override {
45535517e702SDimitry Andric       Status error;
4554ac7ddfbfSEd Maste       const int short_option = m_getopt_table[option_idx].val;
4555ac7ddfbfSEd Maste 
4556435933ddSDimitry Andric       switch (short_option) {
4557ac7ddfbfSEd Maste       case 'c':
4558ac7ddfbfSEd Maste         m_class_name = option_arg;
4559ac7ddfbfSEd Maste         m_sym_ctx_specified = true;
4560ac7ddfbfSEd Maste         break;
4561ac7ddfbfSEd Maste 
4562ac7ddfbfSEd Maste       case 'e':
4563435933ddSDimitry Andric         if (option_arg.getAsInteger(0, m_line_end)) {
4564435933ddSDimitry Andric           error.SetErrorStringWithFormat("invalid end line number: \"%s\"",
4565435933ddSDimitry Andric                                          option_arg.str().c_str());
4566ac7ddfbfSEd Maste           break;
4567ac7ddfbfSEd Maste         }
4568ac7ddfbfSEd Maste         m_sym_ctx_specified = true;
4569ac7ddfbfSEd Maste         break;
4570ac7ddfbfSEd Maste 
4571ac7ddfbfSEd Maste       case 'l':
4572435933ddSDimitry Andric         if (option_arg.getAsInteger(0, m_line_start)) {
4573435933ddSDimitry Andric           error.SetErrorStringWithFormat("invalid start line number: \"%s\"",
4574435933ddSDimitry Andric                                          option_arg.str().c_str());
4575ac7ddfbfSEd Maste           break;
4576ac7ddfbfSEd Maste         }
4577ac7ddfbfSEd Maste         m_sym_ctx_specified = true;
4578ac7ddfbfSEd Maste         break;
4579ac7ddfbfSEd Maste 
4580ac7ddfbfSEd Maste       case 'i':
4581ac7ddfbfSEd Maste         m_no_inlines = true;
4582ac7ddfbfSEd Maste         break;
4583ac7ddfbfSEd Maste 
4584ac7ddfbfSEd Maste       case 'n':
4585ac7ddfbfSEd Maste         m_function_name = option_arg;
4586ac7ddfbfSEd Maste         m_func_name_type_mask |= eFunctionNameTypeAuto;
4587ac7ddfbfSEd Maste         m_sym_ctx_specified = true;
4588ac7ddfbfSEd Maste         break;
4589ac7ddfbfSEd Maste 
4590ac7ddfbfSEd Maste       case 'f':
4591ac7ddfbfSEd Maste         m_file_name = option_arg;
4592ac7ddfbfSEd Maste         m_sym_ctx_specified = true;
4593ac7ddfbfSEd Maste         break;
45944bb0738eSEd Maste 
4595ac7ddfbfSEd Maste       case 's':
4596ac7ddfbfSEd Maste         m_module_name = option_arg;
4597ac7ddfbfSEd Maste         m_sym_ctx_specified = true;
4598ac7ddfbfSEd Maste         break;
45994bb0738eSEd Maste 
4600ac7ddfbfSEd Maste       case 't':
4601435933ddSDimitry Andric         if (option_arg.getAsInteger(0, m_thread_id))
4602435933ddSDimitry Andric           error.SetErrorStringWithFormat("invalid thread id string '%s'",
4603435933ddSDimitry Andric                                          option_arg.str().c_str());
4604ac7ddfbfSEd Maste         m_thread_specified = true;
4605ac7ddfbfSEd Maste         break;
46064bb0738eSEd Maste 
4607ac7ddfbfSEd Maste       case 'T':
4608ac7ddfbfSEd Maste         m_thread_name = option_arg;
4609ac7ddfbfSEd Maste         m_thread_specified = true;
4610ac7ddfbfSEd Maste         break;
46114bb0738eSEd Maste 
4612ac7ddfbfSEd Maste       case 'q':
4613ac7ddfbfSEd Maste         m_queue_name = option_arg;
4614ac7ddfbfSEd Maste         m_thread_specified = true;
4615ac7ddfbfSEd Maste         break;
46164bb0738eSEd Maste 
4617ac7ddfbfSEd Maste       case 'x':
4618435933ddSDimitry Andric         if (option_arg.getAsInteger(0, m_thread_index))
4619435933ddSDimitry Andric           error.SetErrorStringWithFormat("invalid thread index string '%s'",
4620435933ddSDimitry Andric                                          option_arg.str().c_str());
4621ac7ddfbfSEd Maste         m_thread_specified = true;
4622ac7ddfbfSEd Maste         break;
46234bb0738eSEd Maste 
4624ac7ddfbfSEd Maste       case 'o':
4625ac7ddfbfSEd Maste         m_use_one_liner = true;
4626ac7ddfbfSEd Maste         m_one_liner = option_arg;
4627ac7ddfbfSEd Maste         break;
46284bb0738eSEd Maste 
4629ac7ddfbfSEd Maste       default:
4630ac7ddfbfSEd Maste         error.SetErrorStringWithFormat("unrecognized option %c.", short_option);
4631ac7ddfbfSEd Maste         break;
4632ac7ddfbfSEd Maste       }
4633ac7ddfbfSEd Maste       return error;
4634ac7ddfbfSEd Maste     }
4635ac7ddfbfSEd Maste 
OptionParsingStarting(ExecutionContext * execution_context)4636435933ddSDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
4637ac7ddfbfSEd Maste       m_class_name.clear();
4638ac7ddfbfSEd Maste       m_function_name.clear();
4639ac7ddfbfSEd Maste       m_line_start = 0;
4640ac7ddfbfSEd Maste       m_line_end = UINT_MAX;
4641ac7ddfbfSEd Maste       m_file_name.clear();
4642ac7ddfbfSEd Maste       m_module_name.clear();
4643ac7ddfbfSEd Maste       m_func_name_type_mask = eFunctionNameTypeAuto;
4644ac7ddfbfSEd Maste       m_thread_id = LLDB_INVALID_THREAD_ID;
4645ac7ddfbfSEd Maste       m_thread_index = UINT32_MAX;
4646ac7ddfbfSEd Maste       m_thread_name.clear();
4647ac7ddfbfSEd Maste       m_queue_name.clear();
4648ac7ddfbfSEd Maste 
4649ac7ddfbfSEd Maste       m_no_inlines = false;
4650ac7ddfbfSEd Maste       m_sym_ctx_specified = false;
4651ac7ddfbfSEd Maste       m_thread_specified = false;
4652ac7ddfbfSEd Maste 
4653ac7ddfbfSEd Maste       m_use_one_liner = false;
4654ac7ddfbfSEd Maste       m_one_liner.clear();
4655ac7ddfbfSEd Maste     }
4656ac7ddfbfSEd Maste 
4657ac7ddfbfSEd Maste     std::string m_class_name;
4658ac7ddfbfSEd Maste     std::string m_function_name;
4659ac7ddfbfSEd Maste     uint32_t m_line_start;
4660ac7ddfbfSEd Maste     uint32_t m_line_end;
4661ac7ddfbfSEd Maste     std::string m_file_name;
4662ac7ddfbfSEd Maste     std::string m_module_name;
4663ac7ddfbfSEd Maste     uint32_t m_func_name_type_mask; // A pick from lldb::FunctionNameType.
4664ac7ddfbfSEd Maste     lldb::tid_t m_thread_id;
4665ac7ddfbfSEd Maste     uint32_t m_thread_index;
4666ac7ddfbfSEd Maste     std::string m_thread_name;
4667ac7ddfbfSEd Maste     std::string m_queue_name;
4668ac7ddfbfSEd Maste     bool m_sym_ctx_specified;
4669ac7ddfbfSEd Maste     bool m_no_inlines;
4670ac7ddfbfSEd Maste     bool m_thread_specified;
4671ac7ddfbfSEd Maste     // Instance variables to hold the values for one_liner options.
4672ac7ddfbfSEd Maste     bool m_use_one_liner;
4673ac7ddfbfSEd Maste     std::string m_one_liner;
4674ac7ddfbfSEd Maste   };
4675ac7ddfbfSEd Maste 
CommandObjectTargetStopHookAdd(CommandInterpreter & interpreter)4676435933ddSDimitry Andric   CommandObjectTargetStopHookAdd(CommandInterpreter &interpreter)
4677435933ddSDimitry Andric       : CommandObjectParsed(interpreter, "target stop-hook add",
4678ac7ddfbfSEd Maste                             "Add a hook to be executed when the target stops.",
4679ac7ddfbfSEd Maste                             "target stop-hook add"),
4680435933ddSDimitry Andric         IOHandlerDelegateMultiline("DONE",
4681435933ddSDimitry Andric                                    IOHandlerDelegate::Completion::LLDBCommand),
4682435933ddSDimitry Andric         m_options() {}
4683ac7ddfbfSEd Maste 
46844bb0738eSEd Maste   ~CommandObjectTargetStopHookAdd() override = default;
46854bb0738eSEd Maste 
GetOptions()4686435933ddSDimitry Andric   Options *GetOptions() override { return &m_options; }
4687ac7ddfbfSEd Maste 
4688ac7ddfbfSEd Maste protected:
IOHandlerActivated(IOHandler & io_handler)4689435933ddSDimitry Andric   void IOHandlerActivated(IOHandler &io_handler) override {
469012b93ac6SEd Maste     StreamFileSP output_sp(io_handler.GetOutputStreamFile());
4691435933ddSDimitry Andric     if (output_sp) {
4692435933ddSDimitry Andric       output_sp->PutCString(
4693435933ddSDimitry Andric           "Enter your stop hook command(s).  Type 'DONE' to end.\n");
469412b93ac6SEd Maste       output_sp->Flush();
469512b93ac6SEd Maste     }
469612b93ac6SEd Maste   }
469712b93ac6SEd Maste 
IOHandlerInputComplete(IOHandler & io_handler,std::string & line)4698435933ddSDimitry Andric   void IOHandlerInputComplete(IOHandler &io_handler,
4699435933ddSDimitry Andric                               std::string &line) override {
4700435933ddSDimitry Andric     if (m_stop_hook_sp) {
4701435933ddSDimitry Andric       if (line.empty()) {
470212b93ac6SEd Maste         StreamFileSP error_sp(io_handler.GetErrorStreamFile());
4703435933ddSDimitry Andric         if (error_sp) {
4704435933ddSDimitry Andric           error_sp->Printf("error: stop hook #%" PRIu64
4705435933ddSDimitry Andric                            " aborted, no commands.\n",
4706435933ddSDimitry Andric                            m_stop_hook_sp->GetID());
470712b93ac6SEd Maste           error_sp->Flush();
470812b93ac6SEd Maste         }
470912b93ac6SEd Maste         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
471012b93ac6SEd Maste         if (target)
471112b93ac6SEd Maste           target->RemoveStopHookByID(m_stop_hook_sp->GetID());
4712435933ddSDimitry Andric       } else {
471312b93ac6SEd Maste         m_stop_hook_sp->GetCommandPointer()->SplitIntoLines(line);
471412b93ac6SEd Maste         StreamFileSP output_sp(io_handler.GetOutputStreamFile());
4715435933ddSDimitry Andric         if (output_sp) {
4716435933ddSDimitry Andric           output_sp->Printf("Stop hook #%" PRIu64 " added.\n",
4717435933ddSDimitry Andric                             m_stop_hook_sp->GetID());
471812b93ac6SEd Maste           output_sp->Flush();
471912b93ac6SEd Maste         }
472012b93ac6SEd Maste       }
472112b93ac6SEd Maste       m_stop_hook_sp.reset();
472212b93ac6SEd Maste     }
472312b93ac6SEd Maste     io_handler.SetIsDone(true);
472412b93ac6SEd Maste   }
472512b93ac6SEd Maste 
DoExecute(Args & command,CommandReturnObject & result)4726435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
472712b93ac6SEd Maste     m_stop_hook_sp.reset();
472812b93ac6SEd Maste 
47297aa51b79SEd Maste     Target *target = GetSelectedOrDummyTarget();
4730435933ddSDimitry Andric     if (target) {
473112b93ac6SEd Maste       Target::StopHookSP new_hook_sp = target->CreateStopHook();
4732ac7ddfbfSEd Maste 
4733ac7ddfbfSEd Maste       //  First step, make the specifier.
4734ac7ddfbfSEd Maste       std::unique_ptr<SymbolContextSpecifier> specifier_ap;
4735435933ddSDimitry Andric       if (m_options.m_sym_ctx_specified) {
4736435933ddSDimitry Andric         specifier_ap.reset(new SymbolContextSpecifier(
4737435933ddSDimitry Andric             m_interpreter.GetDebugger().GetSelectedTarget()));
4738ac7ddfbfSEd Maste 
4739435933ddSDimitry Andric         if (!m_options.m_module_name.empty()) {
4740435933ddSDimitry Andric           specifier_ap->AddSpecification(
4741435933ddSDimitry Andric               m_options.m_module_name.c_str(),
4742435933ddSDimitry Andric               SymbolContextSpecifier::eModuleSpecified);
4743ac7ddfbfSEd Maste         }
4744ac7ddfbfSEd Maste 
4745435933ddSDimitry Andric         if (!m_options.m_class_name.empty()) {
4746435933ddSDimitry Andric           specifier_ap->AddSpecification(
4747435933ddSDimitry Andric               m_options.m_class_name.c_str(),
4748435933ddSDimitry Andric               SymbolContextSpecifier::eClassOrNamespaceSpecified);
4749ac7ddfbfSEd Maste         }
4750ac7ddfbfSEd Maste 
4751435933ddSDimitry Andric         if (!m_options.m_file_name.empty()) {
4752435933ddSDimitry Andric           specifier_ap->AddSpecification(
4753435933ddSDimitry Andric               m_options.m_file_name.c_str(),
4754435933ddSDimitry Andric               SymbolContextSpecifier::eFileSpecified);
4755ac7ddfbfSEd Maste         }
4756ac7ddfbfSEd Maste 
4757435933ddSDimitry Andric         if (m_options.m_line_start != 0) {
4758435933ddSDimitry Andric           specifier_ap->AddLineSpecification(
4759435933ddSDimitry Andric               m_options.m_line_start,
4760435933ddSDimitry Andric               SymbolContextSpecifier::eLineStartSpecified);
4761ac7ddfbfSEd Maste         }
4762ac7ddfbfSEd Maste 
4763435933ddSDimitry Andric         if (m_options.m_line_end != UINT_MAX) {
4764435933ddSDimitry Andric           specifier_ap->AddLineSpecification(
4765435933ddSDimitry Andric               m_options.m_line_end, SymbolContextSpecifier::eLineEndSpecified);
4766ac7ddfbfSEd Maste         }
4767ac7ddfbfSEd Maste 
4768435933ddSDimitry Andric         if (!m_options.m_function_name.empty()) {
4769435933ddSDimitry Andric           specifier_ap->AddSpecification(
4770435933ddSDimitry Andric               m_options.m_function_name.c_str(),
4771435933ddSDimitry Andric               SymbolContextSpecifier::eFunctionSpecified);
4772ac7ddfbfSEd Maste         }
4773ac7ddfbfSEd Maste       }
4774ac7ddfbfSEd Maste 
47754bb0738eSEd Maste       if (specifier_ap)
4776ac7ddfbfSEd Maste         new_hook_sp->SetSpecifier(specifier_ap.release());
4777ac7ddfbfSEd Maste 
4778ac7ddfbfSEd Maste       // Next see if any of the thread options have been entered:
4779ac7ddfbfSEd Maste 
4780435933ddSDimitry Andric       if (m_options.m_thread_specified) {
4781ac7ddfbfSEd Maste         ThreadSpec *thread_spec = new ThreadSpec();
4782ac7ddfbfSEd Maste 
4783435933ddSDimitry Andric         if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID) {
4784ac7ddfbfSEd Maste           thread_spec->SetTID(m_options.m_thread_id);
4785ac7ddfbfSEd Maste         }
4786ac7ddfbfSEd Maste 
4787ac7ddfbfSEd Maste         if (m_options.m_thread_index != UINT32_MAX)
4788ac7ddfbfSEd Maste           thread_spec->SetIndex(m_options.m_thread_index);
4789ac7ddfbfSEd Maste 
4790ac7ddfbfSEd Maste         if (!m_options.m_thread_name.empty())
4791ac7ddfbfSEd Maste           thread_spec->SetName(m_options.m_thread_name.c_str());
4792ac7ddfbfSEd Maste 
4793ac7ddfbfSEd Maste         if (!m_options.m_queue_name.empty())
4794ac7ddfbfSEd Maste           thread_spec->SetQueueName(m_options.m_queue_name.c_str());
4795ac7ddfbfSEd Maste 
4796ac7ddfbfSEd Maste         new_hook_sp->SetThreadSpecifier(thread_spec);
4797ac7ddfbfSEd Maste       }
4798435933ddSDimitry Andric       if (m_options.m_use_one_liner) {
4799ac7ddfbfSEd Maste         // Use one-liner.
4800435933ddSDimitry Andric         new_hook_sp->GetCommandPointer()->AppendString(
4801435933ddSDimitry Andric             m_options.m_one_liner.c_str());
4802435933ddSDimitry Andric         result.AppendMessageWithFormat("Stop hook #%" PRIu64 " added.\n",
4803435933ddSDimitry Andric                                        new_hook_sp->GetID());
4804435933ddSDimitry Andric       } else {
480512b93ac6SEd Maste         m_stop_hook_sp = new_hook_sp;
4806435933ddSDimitry Andric         m_interpreter.GetLLDBCommandsFromIOHandler(
4807435933ddSDimitry Andric             "> ",     // Prompt
480812b93ac6SEd Maste             *this,    // IOHandlerDelegate
480912b93ac6SEd Maste             true,     // Run IOHandler in async mode
4810435933ddSDimitry Andric             nullptr); // Baton for the "io_handler" that will be passed back
4811435933ddSDimitry Andric                       // into our IOHandlerDelegate functions
4812ac7ddfbfSEd Maste       }
4813ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusSuccessFinishNoResult);
4814435933ddSDimitry Andric     } else {
4815ac7ddfbfSEd Maste       result.AppendError("invalid target\n");
4816ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
4817ac7ddfbfSEd Maste     }
4818ac7ddfbfSEd Maste 
4819ac7ddfbfSEd Maste     return result.Succeeded();
4820ac7ddfbfSEd Maste   }
48214bb0738eSEd Maste 
4822ac7ddfbfSEd Maste private:
4823ac7ddfbfSEd Maste   CommandOptions m_options;
482412b93ac6SEd Maste   Target::StopHookSP m_stop_hook_sp;
4825ac7ddfbfSEd Maste };
4826ac7ddfbfSEd Maste 
4827ac7ddfbfSEd Maste #pragma mark CommandObjectTargetStopHookDelete
4828ac7ddfbfSEd Maste 
4829ac7ddfbfSEd Maste //-------------------------------------------------------------------------
4830ac7ddfbfSEd Maste // CommandObjectTargetStopHookDelete
4831ac7ddfbfSEd Maste //-------------------------------------------------------------------------
4832ac7ddfbfSEd Maste 
4833435933ddSDimitry Andric class CommandObjectTargetStopHookDelete : public CommandObjectParsed {
4834ac7ddfbfSEd Maste public:
CommandObjectTargetStopHookDelete(CommandInterpreter & interpreter)4835435933ddSDimitry Andric   CommandObjectTargetStopHookDelete(CommandInterpreter &interpreter)
4836435933ddSDimitry Andric       : CommandObjectParsed(interpreter, "target stop-hook delete",
4837ac7ddfbfSEd Maste                             "Delete a stop-hook.",
4838435933ddSDimitry Andric                             "target stop-hook delete [<idx>]") {}
4839ac7ddfbfSEd Maste 
48404bb0738eSEd Maste   ~CommandObjectTargetStopHookDelete() override = default;
4841ac7ddfbfSEd Maste 
4842ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)4843435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
48447aa51b79SEd Maste     Target *target = GetSelectedOrDummyTarget();
4845435933ddSDimitry Andric     if (target) {
4846ac7ddfbfSEd Maste       // FIXME: see if we can use the breakpoint id style parser?
4847ac7ddfbfSEd Maste       size_t num_args = command.GetArgumentCount();
4848435933ddSDimitry Andric       if (num_args == 0) {
4849435933ddSDimitry Andric         if (!m_interpreter.Confirm("Delete all stop hooks?", true)) {
4850ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusFailed);
4851ac7ddfbfSEd Maste           return false;
4852435933ddSDimitry Andric         } else {
4853ac7ddfbfSEd Maste           target->RemoveAllStopHooks();
4854ac7ddfbfSEd Maste         }
4855435933ddSDimitry Andric       } else {
4856ac7ddfbfSEd Maste         bool success;
4857435933ddSDimitry Andric         for (size_t i = 0; i < num_args; i++) {
4858435933ddSDimitry Andric           lldb::user_id_t user_id = StringConvert::ToUInt32(
4859435933ddSDimitry Andric               command.GetArgumentAtIndex(i), 0, 0, &success);
4860435933ddSDimitry Andric           if (!success) {
4861435933ddSDimitry Andric             result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n",
4862435933ddSDimitry Andric                                          command.GetArgumentAtIndex(i));
4863ac7ddfbfSEd Maste             result.SetStatus(eReturnStatusFailed);
4864ac7ddfbfSEd Maste             return false;
4865ac7ddfbfSEd Maste           }
4866ac7ddfbfSEd Maste           success = target->RemoveStopHookByID(user_id);
4867435933ddSDimitry Andric           if (!success) {
4868435933ddSDimitry Andric             result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n",
4869435933ddSDimitry Andric                                          command.GetArgumentAtIndex(i));
4870ac7ddfbfSEd Maste             result.SetStatus(eReturnStatusFailed);
4871ac7ddfbfSEd Maste             return false;
4872ac7ddfbfSEd Maste           }
4873ac7ddfbfSEd Maste         }
4874ac7ddfbfSEd Maste       }
4875ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusSuccessFinishNoResult);
4876435933ddSDimitry Andric     } else {
4877ac7ddfbfSEd Maste       result.AppendError("invalid target\n");
4878ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
4879ac7ddfbfSEd Maste     }
4880ac7ddfbfSEd Maste 
4881ac7ddfbfSEd Maste     return result.Succeeded();
4882ac7ddfbfSEd Maste   }
4883ac7ddfbfSEd Maste };
48844bb0738eSEd Maste 
4885ac7ddfbfSEd Maste #pragma mark CommandObjectTargetStopHookEnableDisable
4886ac7ddfbfSEd Maste 
4887ac7ddfbfSEd Maste //-------------------------------------------------------------------------
4888ac7ddfbfSEd Maste // CommandObjectTargetStopHookEnableDisable
4889ac7ddfbfSEd Maste //-------------------------------------------------------------------------
4890ac7ddfbfSEd Maste 
4891435933ddSDimitry Andric class CommandObjectTargetStopHookEnableDisable : public CommandObjectParsed {
4892ac7ddfbfSEd Maste public:
CommandObjectTargetStopHookEnableDisable(CommandInterpreter & interpreter,bool enable,const char * name,const char * help,const char * syntax)4893435933ddSDimitry Andric   CommandObjectTargetStopHookEnableDisable(CommandInterpreter &interpreter,
4894435933ddSDimitry Andric                                            bool enable, const char *name,
4895435933ddSDimitry Andric                                            const char *help, const char *syntax)
4896435933ddSDimitry Andric       : CommandObjectParsed(interpreter, name, help, syntax), m_enable(enable) {
4897ac7ddfbfSEd Maste   }
4898ac7ddfbfSEd Maste 
48994bb0738eSEd Maste   ~CommandObjectTargetStopHookEnableDisable() override = default;
4900ac7ddfbfSEd Maste 
4901ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)4902435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
49037aa51b79SEd Maste     Target *target = GetSelectedOrDummyTarget();
4904435933ddSDimitry Andric     if (target) {
4905ac7ddfbfSEd Maste       // FIXME: see if we can use the breakpoint id style parser?
4906ac7ddfbfSEd Maste       size_t num_args = command.GetArgumentCount();
4907ac7ddfbfSEd Maste       bool success;
4908ac7ddfbfSEd Maste 
4909435933ddSDimitry Andric       if (num_args == 0) {
4910ac7ddfbfSEd Maste         target->SetAllStopHooksActiveState(m_enable);
4911435933ddSDimitry Andric       } else {
4912435933ddSDimitry Andric         for (size_t i = 0; i < num_args; i++) {
4913435933ddSDimitry Andric           lldb::user_id_t user_id = StringConvert::ToUInt32(
4914435933ddSDimitry Andric               command.GetArgumentAtIndex(i), 0, 0, &success);
4915435933ddSDimitry Andric           if (!success) {
4916435933ddSDimitry Andric             result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n",
4917435933ddSDimitry Andric                                          command.GetArgumentAtIndex(i));
4918ac7ddfbfSEd Maste             result.SetStatus(eReturnStatusFailed);
4919ac7ddfbfSEd Maste             return false;
4920ac7ddfbfSEd Maste           }
4921ac7ddfbfSEd Maste           success = target->SetStopHookActiveStateByID(user_id, m_enable);
4922435933ddSDimitry Andric           if (!success) {
4923435933ddSDimitry Andric             result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n",
4924435933ddSDimitry Andric                                          command.GetArgumentAtIndex(i));
4925ac7ddfbfSEd Maste             result.SetStatus(eReturnStatusFailed);
4926ac7ddfbfSEd Maste             return false;
4927ac7ddfbfSEd Maste           }
4928ac7ddfbfSEd Maste         }
4929ac7ddfbfSEd Maste       }
4930ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusSuccessFinishNoResult);
4931435933ddSDimitry Andric     } else {
4932ac7ddfbfSEd Maste       result.AppendError("invalid target\n");
4933ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
4934ac7ddfbfSEd Maste     }
4935ac7ddfbfSEd Maste     return result.Succeeded();
4936ac7ddfbfSEd Maste   }
4937435933ddSDimitry Andric 
4938ac7ddfbfSEd Maste private:
4939ac7ddfbfSEd Maste   bool m_enable;
4940ac7ddfbfSEd Maste };
4941ac7ddfbfSEd Maste 
4942ac7ddfbfSEd Maste #pragma mark CommandObjectTargetStopHookList
4943ac7ddfbfSEd Maste 
4944ac7ddfbfSEd Maste //-------------------------------------------------------------------------
4945ac7ddfbfSEd Maste // CommandObjectTargetStopHookList
4946ac7ddfbfSEd Maste //-------------------------------------------------------------------------
4947ac7ddfbfSEd Maste 
4948435933ddSDimitry Andric class CommandObjectTargetStopHookList : public CommandObjectParsed {
4949ac7ddfbfSEd Maste public:
CommandObjectTargetStopHookList(CommandInterpreter & interpreter)4950435933ddSDimitry Andric   CommandObjectTargetStopHookList(CommandInterpreter &interpreter)
4951435933ddSDimitry Andric       : CommandObjectParsed(interpreter, "target stop-hook list",
4952ac7ddfbfSEd Maste                             "List all stop-hooks.",
4953435933ddSDimitry Andric                             "target stop-hook list [<type>]") {}
4954ac7ddfbfSEd Maste 
49554bb0738eSEd Maste   ~CommandObjectTargetStopHookList() override = default;
4956ac7ddfbfSEd Maste 
4957ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)4958435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
49597aa51b79SEd Maste     Target *target = GetSelectedOrDummyTarget();
4960435933ddSDimitry Andric     if (!target) {
4961ac7ddfbfSEd Maste       result.AppendError("invalid target\n");
4962ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
4963ac7ddfbfSEd Maste       return result.Succeeded();
4964ac7ddfbfSEd Maste     }
4965ac7ddfbfSEd Maste 
4966ac7ddfbfSEd Maste     size_t num_hooks = target->GetNumStopHooks();
4967435933ddSDimitry Andric     if (num_hooks == 0) {
4968ac7ddfbfSEd Maste       result.GetOutputStream().PutCString("No stop hooks.\n");
4969435933ddSDimitry Andric     } else {
4970435933ddSDimitry Andric       for (size_t i = 0; i < num_hooks; i++) {
4971ac7ddfbfSEd Maste         Target::StopHookSP this_hook = target->GetStopHookAtIndex(i);
4972ac7ddfbfSEd Maste         if (i > 0)
4973ac7ddfbfSEd Maste           result.GetOutputStream().PutCString("\n");
4974435933ddSDimitry Andric         this_hook->GetDescription(&(result.GetOutputStream()),
4975435933ddSDimitry Andric                                   eDescriptionLevelFull);
4976ac7ddfbfSEd Maste       }
4977ac7ddfbfSEd Maste     }
4978ac7ddfbfSEd Maste     result.SetStatus(eReturnStatusSuccessFinishResult);
4979ac7ddfbfSEd Maste     return result.Succeeded();
4980ac7ddfbfSEd Maste   }
4981ac7ddfbfSEd Maste };
4982ac7ddfbfSEd Maste 
4983ac7ddfbfSEd Maste #pragma mark CommandObjectMultiwordTargetStopHooks
49844bb0738eSEd Maste 
4985ac7ddfbfSEd Maste //-------------------------------------------------------------------------
4986ac7ddfbfSEd Maste // CommandObjectMultiwordTargetStopHooks
4987ac7ddfbfSEd Maste //-------------------------------------------------------------------------
4988ac7ddfbfSEd Maste 
4989435933ddSDimitry Andric class CommandObjectMultiwordTargetStopHooks : public CommandObjectMultiword {
4990ac7ddfbfSEd Maste public:
CommandObjectMultiwordTargetStopHooks(CommandInterpreter & interpreter)49914bb0738eSEd Maste   CommandObjectMultiwordTargetStopHooks(CommandInterpreter &interpreter)
4992435933ddSDimitry Andric       : CommandObjectMultiword(
4993435933ddSDimitry Andric             interpreter, "target stop-hook",
49944bb0738eSEd Maste             "Commands for operating on debugger target stop-hooks.",
4995435933ddSDimitry Andric             "target stop-hook <subcommand> [<subcommand-options>]") {
4996435933ddSDimitry Andric     LoadSubCommand("add", CommandObjectSP(
4997435933ddSDimitry Andric                               new CommandObjectTargetStopHookAdd(interpreter)));
4998435933ddSDimitry Andric     LoadSubCommand(
4999435933ddSDimitry Andric         "delete",
5000435933ddSDimitry Andric         CommandObjectSP(new CommandObjectTargetStopHookDelete(interpreter)));
5001435933ddSDimitry Andric     LoadSubCommand("disable",
5002435933ddSDimitry Andric                    CommandObjectSP(new CommandObjectTargetStopHookEnableDisable(
5003435933ddSDimitry Andric                        interpreter, false, "target stop-hook disable [<id>]",
5004435933ddSDimitry Andric                        "Disable a stop-hook.", "target stop-hook disable")));
5005435933ddSDimitry Andric     LoadSubCommand("enable",
5006435933ddSDimitry Andric                    CommandObjectSP(new CommandObjectTargetStopHookEnableDisable(
5007435933ddSDimitry Andric                        interpreter, true, "target stop-hook enable [<id>]",
5008435933ddSDimitry Andric                        "Enable a stop-hook.", "target stop-hook enable")));
5009435933ddSDimitry Andric     LoadSubCommand("list", CommandObjectSP(new CommandObjectTargetStopHookList(
5010435933ddSDimitry Andric                                interpreter)));
5011ac7ddfbfSEd Maste   }
5012ac7ddfbfSEd Maste 
50134bb0738eSEd Maste   ~CommandObjectMultiwordTargetStopHooks() override = default;
5014ac7ddfbfSEd Maste };
5015ac7ddfbfSEd Maste 
5016ac7ddfbfSEd Maste #pragma mark CommandObjectMultiwordTarget
5017ac7ddfbfSEd Maste 
5018ac7ddfbfSEd Maste //-------------------------------------------------------------------------
5019ac7ddfbfSEd Maste // CommandObjectMultiwordTarget
5020ac7ddfbfSEd Maste //-------------------------------------------------------------------------
5021ac7ddfbfSEd Maste 
CommandObjectMultiwordTarget(CommandInterpreter & interpreter)5022435933ddSDimitry Andric CommandObjectMultiwordTarget::CommandObjectMultiwordTarget(
5023435933ddSDimitry Andric     CommandInterpreter &interpreter)
5024435933ddSDimitry Andric     : CommandObjectMultiword(interpreter, "target",
5025435933ddSDimitry Andric                              "Commands for operating on debugger targets.",
5026435933ddSDimitry Andric                              "target <subcommand> [<subcommand-options>]") {
5027435933ddSDimitry Andric   LoadSubCommand("create",
5028435933ddSDimitry Andric                  CommandObjectSP(new CommandObjectTargetCreate(interpreter)));
5029435933ddSDimitry Andric   LoadSubCommand("delete",
5030435933ddSDimitry Andric                  CommandObjectSP(new CommandObjectTargetDelete(interpreter)));
5031435933ddSDimitry Andric   LoadSubCommand("list",
5032435933ddSDimitry Andric                  CommandObjectSP(new CommandObjectTargetList(interpreter)));
5033435933ddSDimitry Andric   LoadSubCommand("select",
5034435933ddSDimitry Andric                  CommandObjectSP(new CommandObjectTargetSelect(interpreter)));
5035435933ddSDimitry Andric   LoadSubCommand(
5036435933ddSDimitry Andric       "stop-hook",
5037435933ddSDimitry Andric       CommandObjectSP(new CommandObjectMultiwordTargetStopHooks(interpreter)));
5038435933ddSDimitry Andric   LoadSubCommand("modules",
5039435933ddSDimitry Andric                  CommandObjectSP(new CommandObjectTargetModules(interpreter)));
5040435933ddSDimitry Andric   LoadSubCommand("symbols",
5041435933ddSDimitry Andric                  CommandObjectSP(new CommandObjectTargetSymbols(interpreter)));
5042435933ddSDimitry Andric   LoadSubCommand("variable",
5043435933ddSDimitry Andric                  CommandObjectSP(new CommandObjectTargetVariable(interpreter)));
5044ac7ddfbfSEd Maste }
5045ac7ddfbfSEd Maste 
50464bb0738eSEd Maste CommandObjectMultiwordTarget::~CommandObjectMultiwordTarget() = default;
5047