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