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

source code of lldb/source/Commands/CommandObjectTarget.cpp