Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / lldb / source / Commands / CommandObjectTarget.cpp
blobc84a6550d6c75cc3836b77f569a10b5ead858d24
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 //===----------------------------------------------------------------------===//
9 #include "CommandObjectTarget.h"
11 #include "lldb/Core/Debugger.h"
12 #include "lldb/Core/IOHandler.h"
13 #include "lldb/Core/Module.h"
14 #include "lldb/Core/ModuleSpec.h"
15 #include "lldb/Core/Section.h"
16 #include "lldb/Core/ValueObjectVariable.h"
17 #include "lldb/DataFormatters/ValueObjectPrinter.h"
18 #include "lldb/Host/OptionParser.h"
19 #include "lldb/Interpreter/CommandInterpreter.h"
20 #include "lldb/Interpreter/CommandOptionArgumentTable.h"
21 #include "lldb/Interpreter/CommandReturnObject.h"
22 #include "lldb/Interpreter/OptionArgParser.h"
23 #include "lldb/Interpreter/OptionGroupArchitecture.h"
24 #include "lldb/Interpreter/OptionGroupBoolean.h"
25 #include "lldb/Interpreter/OptionGroupFile.h"
26 #include "lldb/Interpreter/OptionGroupFormat.h"
27 #include "lldb/Interpreter/OptionGroupPlatform.h"
28 #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"
29 #include "lldb/Interpreter/OptionGroupString.h"
30 #include "lldb/Interpreter/OptionGroupUInt64.h"
31 #include "lldb/Interpreter/OptionGroupUUID.h"
32 #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
33 #include "lldb/Interpreter/OptionGroupVariable.h"
34 #include "lldb/Interpreter/Options.h"
35 #include "lldb/Symbol/CompileUnit.h"
36 #include "lldb/Symbol/FuncUnwinders.h"
37 #include "lldb/Symbol/LineTable.h"
38 #include "lldb/Symbol/LocateSymbolFile.h"
39 #include "lldb/Symbol/ObjectFile.h"
40 #include "lldb/Symbol/SymbolFile.h"
41 #include "lldb/Symbol/UnwindPlan.h"
42 #include "lldb/Symbol/VariableList.h"
43 #include "lldb/Target/ABI.h"
44 #include "lldb/Target/Process.h"
45 #include "lldb/Target/RegisterContext.h"
46 #include "lldb/Target/SectionLoadList.h"
47 #include "lldb/Target/StackFrame.h"
48 #include "lldb/Target/Thread.h"
49 #include "lldb/Target/ThreadSpec.h"
50 #include "lldb/Utility/Args.h"
51 #include "lldb/Utility/ConstString.h"
52 #include "lldb/Utility/FileSpec.h"
53 #include "lldb/Utility/LLDBLog.h"
54 #include "lldb/Utility/State.h"
55 #include "lldb/Utility/StructuredData.h"
56 #include "lldb/Utility/Timer.h"
57 #include "lldb/lldb-enumerations.h"
58 #include "lldb/lldb-private-enumerations.h"
60 #include "clang/CodeGen/ObjectFilePCHContainerOperations.h"
61 #include "clang/Frontend/CompilerInstance.h"
62 #include "clang/Frontend/CompilerInvocation.h"
63 #include "clang/Frontend/FrontendActions.h"
64 #include "llvm/ADT/ScopeExit.h"
65 #include "llvm/ADT/StringRef.h"
66 #include "llvm/Support/FileSystem.h"
67 #include "llvm/Support/FormatAdapters.h"
70 using namespace lldb;
71 using namespace lldb_private;
73 static void DumpTargetInfo(uint32_t target_idx, Target *target,
74 const char *prefix_cstr,
75 bool show_stopped_process_status, Stream &strm) {
76 const ArchSpec &target_arch = target->GetArchitecture();
78 Module *exe_module = target->GetExecutableModulePointer();
79 char exe_path[PATH_MAX];
80 bool exe_valid = false;
81 if (exe_module)
82 exe_valid = exe_module->GetFileSpec().GetPath(exe_path, sizeof(exe_path));
84 if (!exe_valid)
85 ::strcpy(exe_path, "<none>");
87 std::string formatted_label = "";
88 const std::string &label = target->GetLabel();
89 if (!label.empty()) {
90 formatted_label = " (" + label + ")";
93 strm.Printf("%starget #%u%s: %s", prefix_cstr ? prefix_cstr : "", target_idx,
94 formatted_label.data(), exe_path);
96 uint32_t properties = 0;
97 if (target_arch.IsValid()) {
98 strm.Printf("%sarch=", properties++ > 0 ? ", " : " ( ");
99 target_arch.DumpTriple(strm.AsRawOstream());
100 properties++;
102 PlatformSP platform_sp(target->GetPlatform());
103 if (platform_sp)
104 strm.Format("{0}platform={1}", properties++ > 0 ? ", " : " ( ",
105 platform_sp->GetName());
107 ProcessSP process_sp(target->GetProcessSP());
108 bool show_process_status = false;
109 if (process_sp) {
110 lldb::pid_t pid = process_sp->GetID();
111 StateType state = process_sp->GetState();
112 if (show_stopped_process_status)
113 show_process_status = StateIsStoppedState(state, true);
114 const char *state_cstr = StateAsCString(state);
115 if (pid != LLDB_INVALID_PROCESS_ID)
116 strm.Printf("%spid=%" PRIu64, properties++ > 0 ? ", " : " ( ", pid);
117 strm.Printf("%sstate=%s", properties++ > 0 ? ", " : " ( ", state_cstr);
119 if (properties > 0)
120 strm.PutCString(" )\n");
121 else
122 strm.EOL();
123 if (show_process_status) {
124 const bool only_threads_with_stop_reason = true;
125 const uint32_t start_frame = 0;
126 const uint32_t num_frames = 1;
127 const uint32_t num_frames_with_source = 1;
128 const bool stop_format = false;
129 process_sp->GetStatus(strm);
130 process_sp->GetThreadStatus(strm, only_threads_with_stop_reason,
131 start_frame, num_frames, num_frames_with_source,
132 stop_format);
136 static uint32_t DumpTargetList(TargetList &target_list,
137 bool show_stopped_process_status, Stream &strm) {
138 const uint32_t num_targets = target_list.GetNumTargets();
139 if (num_targets) {
140 TargetSP selected_target_sp(target_list.GetSelectedTarget());
141 strm.PutCString("Current targets:\n");
142 for (uint32_t i = 0; i < num_targets; ++i) {
143 TargetSP target_sp(target_list.GetTargetAtIndex(i));
144 if (target_sp) {
145 bool is_selected = target_sp.get() == selected_target_sp.get();
146 DumpTargetInfo(i, target_sp.get(), is_selected ? "* " : " ",
147 show_stopped_process_status, strm);
151 return num_targets;
154 #define LLDB_OPTIONS_target_dependents
155 #include "CommandOptions.inc"
157 class OptionGroupDependents : public OptionGroup {
158 public:
159 OptionGroupDependents() = default;
161 ~OptionGroupDependents() override = default;
163 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
164 return llvm::ArrayRef(g_target_dependents_options);
167 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
168 ExecutionContext *execution_context) override {
169 Status error;
171 // For compatibility no value means don't load dependents.
172 if (option_value.empty()) {
173 m_load_dependent_files = eLoadDependentsNo;
174 return error;
177 const char short_option =
178 g_target_dependents_options[option_idx].short_option;
179 if (short_option == 'd') {
180 LoadDependentFiles tmp_load_dependents;
181 tmp_load_dependents = (LoadDependentFiles)OptionArgParser::ToOptionEnum(
182 option_value, g_target_dependents_options[option_idx].enum_values, 0,
183 error);
184 if (error.Success())
185 m_load_dependent_files = tmp_load_dependents;
186 } else {
187 error.SetErrorStringWithFormat("unrecognized short option '%c'",
188 short_option);
191 return error;
194 Status SetOptionValue(uint32_t, const char *, ExecutionContext *) = delete;
196 void OptionParsingStarting(ExecutionContext *execution_context) override {
197 m_load_dependent_files = eLoadDependentsDefault;
200 LoadDependentFiles m_load_dependent_files;
202 private:
203 OptionGroupDependents(const OptionGroupDependents &) = delete;
204 const OptionGroupDependents &
205 operator=(const OptionGroupDependents &) = delete;
208 #pragma mark CommandObjectTargetCreate
210 class CommandObjectTargetCreate : public CommandObjectParsed {
211 public:
212 CommandObjectTargetCreate(CommandInterpreter &interpreter)
213 : CommandObjectParsed(
214 interpreter, "target create",
215 "Create a target using the argument as the main executable.",
216 nullptr),
217 m_platform_options(true), // Include the --platform option.
218 m_core_file(LLDB_OPT_SET_1, false, "core", 'c', 0, eArgTypeFilename,
219 "Fullpath to a core file to use for this target."),
220 m_label(LLDB_OPT_SET_1, false, "label", 'l', 0, eArgTypeName,
221 "Optional name for this target.", nullptr),
222 m_symbol_file(LLDB_OPT_SET_1, false, "symfile", 's', 0,
223 eArgTypeFilename,
224 "Fullpath to a stand alone debug "
225 "symbols file for when debug symbols "
226 "are not in the executable."),
227 m_remote_file(
228 LLDB_OPT_SET_1, false, "remote-file", 'r', 0, eArgTypeFilename,
229 "Fullpath to the file on the remote host if debugging remotely.") {
230 CommandArgumentEntry arg;
231 CommandArgumentData file_arg;
233 // Define the first (and only) variant of this arg.
234 file_arg.arg_type = eArgTypeFilename;
235 file_arg.arg_repetition = eArgRepeatPlain;
237 // There is only one variant this argument could be; put it into the
238 // argument entry.
239 arg.push_back(file_arg);
241 // Push the data for the first argument into the m_arguments vector.
242 m_arguments.push_back(arg);
244 m_option_group.Append(&m_arch_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
245 m_option_group.Append(&m_platform_options, LLDB_OPT_SET_ALL, 1);
246 m_option_group.Append(&m_core_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
247 m_option_group.Append(&m_label, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
248 m_option_group.Append(&m_symbol_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
249 m_option_group.Append(&m_remote_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
250 m_option_group.Append(&m_add_dependents, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
251 m_option_group.Finalize();
254 ~CommandObjectTargetCreate() override = default;
256 Options *GetOptions() override { return &m_option_group; }
258 void
259 HandleArgumentCompletion(CompletionRequest &request,
260 OptionElementVector &opt_element_vector) override {
261 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
262 GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr);
265 protected:
266 void DoExecute(Args &command, CommandReturnObject &result) override {
267 const size_t argc = command.GetArgumentCount();
268 FileSpec core_file(m_core_file.GetOptionValue().GetCurrentValue());
269 FileSpec remote_file(m_remote_file.GetOptionValue().GetCurrentValue());
271 if (core_file) {
272 auto file = FileSystem::Instance().Open(
273 core_file, lldb_private::File::eOpenOptionReadOnly);
275 if (!file) {
276 result.AppendErrorWithFormatv("Cannot open '{0}': {1}.",
277 core_file.GetPath(),
278 llvm::toString(file.takeError()));
279 return;
283 if (argc == 1 || core_file || remote_file) {
284 FileSpec symfile(m_symbol_file.GetOptionValue().GetCurrentValue());
285 if (symfile) {
286 auto file = FileSystem::Instance().Open(
287 symfile, lldb_private::File::eOpenOptionReadOnly);
289 if (!file) {
290 result.AppendErrorWithFormatv("Cannot open '{0}': {1}.",
291 symfile.GetPath(),
292 llvm::toString(file.takeError()));
293 return;
297 const char *file_path = command.GetArgumentAtIndex(0);
298 LLDB_SCOPED_TIMERF("(lldb) target create '%s'", file_path);
300 bool must_set_platform_path = false;
302 Debugger &debugger = GetDebugger();
304 TargetSP target_sp;
305 llvm::StringRef arch_cstr = m_arch_option.GetArchitectureName();
306 Status error(debugger.GetTargetList().CreateTarget(
307 debugger, file_path, arch_cstr,
308 m_add_dependents.m_load_dependent_files, &m_platform_options,
309 target_sp));
311 if (!target_sp) {
312 result.AppendError(error.AsCString());
313 return;
316 const llvm::StringRef label =
317 m_label.GetOptionValue().GetCurrentValueAsRef();
318 if (!label.empty()) {
319 if (auto E = target_sp->SetLabel(label))
320 result.SetError(std::move(E));
321 return;
324 auto on_error = llvm::make_scope_exit(
325 [&target_list = debugger.GetTargetList(), &target_sp]() {
326 target_list.DeleteTarget(target_sp);
329 // Only get the platform after we create the target because we might
330 // have switched platforms depending on what the arguments were to
331 // CreateTarget() we can't rely on the selected platform.
333 PlatformSP platform_sp = target_sp->GetPlatform();
335 FileSpec file_spec;
336 if (file_path) {
337 file_spec.SetFile(file_path, FileSpec::Style::native);
338 FileSystem::Instance().Resolve(file_spec);
340 // Try to resolve the exe based on PATH and/or platform-specific
341 // suffixes, but only if using the host platform.
342 if (platform_sp && platform_sp->IsHost() &&
343 !FileSystem::Instance().Exists(file_spec))
344 FileSystem::Instance().ResolveExecutableLocation(file_spec);
347 if (remote_file) {
348 if (platform_sp) {
349 // I have a remote file.. two possible cases
350 if (file_spec && FileSystem::Instance().Exists(file_spec)) {
351 // if the remote file does not exist, push it there
352 if (!platform_sp->GetFileExists(remote_file)) {
353 Status err = platform_sp->PutFile(file_spec, remote_file);
354 if (err.Fail()) {
355 result.AppendError(err.AsCString());
356 return;
359 } else {
360 // there is no local file and we need one
361 // in order to make the remote ---> local transfer we need a
362 // platform
363 // TODO: if the user has passed in a --platform argument, use it
364 // to fetch the right platform
365 if (file_path) {
366 // copy the remote file to the local file
367 Status err = platform_sp->GetFile(remote_file, file_spec);
368 if (err.Fail()) {
369 result.AppendError(err.AsCString());
370 return;
372 } else {
373 // If the remote file exists, we can debug reading that out of
374 // memory. If the platform is already connected to an lldb-server
375 // then we can at least check the file exists remotely. Otherwise
376 // we'll just have to trust that it will be there when we do
377 // process connect.
378 // I don't do this for the host platform because it seems odd to
379 // support supplying a remote file but no local file for a local
380 // debug session.
381 if (platform_sp->IsHost()) {
382 result.AppendError("Supply a local file, not a remote file, "
383 "when debugging on the host.");
384 return;
386 if (platform_sp->IsConnected() && !platform_sp->GetFileExists(remote_file)) {
387 result.AppendError("remote --> local transfer without local "
388 "path is not implemented yet");
389 return;
391 // Since there's only a remote file, we need to set the executable
392 // file spec to the remote one.
393 ProcessLaunchInfo launch_info = target_sp->GetProcessLaunchInfo();
394 launch_info.SetExecutableFile(FileSpec(remote_file), true);
395 target_sp->SetProcessLaunchInfo(launch_info);
398 } else {
399 result.AppendError("no platform found for target");
400 return;
404 if (symfile || remote_file) {
405 ModuleSP module_sp(target_sp->GetExecutableModule());
406 if (module_sp) {
407 if (symfile)
408 module_sp->SetSymbolFileFileSpec(symfile);
409 if (remote_file) {
410 std::string remote_path = remote_file.GetPath();
411 target_sp->SetArg0(remote_path.c_str());
412 module_sp->SetPlatformFileSpec(remote_file);
417 if (must_set_platform_path) {
418 ModuleSpec main_module_spec(file_spec);
419 ModuleSP module_sp =
420 target_sp->GetOrCreateModule(main_module_spec, true /* notify */);
421 if (module_sp)
422 module_sp->SetPlatformFileSpec(remote_file);
425 if (core_file) {
426 FileSpec core_file_dir;
427 core_file_dir.SetDirectory(core_file.GetDirectory());
428 target_sp->AppendExecutableSearchPaths(core_file_dir);
430 ProcessSP process_sp(target_sp->CreateProcess(
431 GetDebugger().GetListener(), llvm::StringRef(), &core_file, false));
433 if (process_sp) {
434 // Seems weird that we Launch a core file, but that is what we
435 // do!
436 error = process_sp->LoadCore();
438 if (error.Fail()) {
439 result.AppendError(
440 error.AsCString("can't find plug-in for core file"));
441 return;
442 } else {
443 result.AppendMessageWithFormatv(
444 "Core file '{0}' ({1}) was loaded.\n", core_file.GetPath(),
445 target_sp->GetArchitecture().GetArchitectureName());
446 result.SetStatus(eReturnStatusSuccessFinishNoResult);
447 on_error.release();
449 } else {
450 result.AppendErrorWithFormatv(
451 "Unable to find process plug-in for core file '{0}'\n",
452 core_file.GetPath());
454 } else {
455 result.AppendMessageWithFormat(
456 "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();
462 } else {
463 result.AppendErrorWithFormat("'%s' takes exactly one executable path "
464 "argument, or use the --core option.\n",
465 m_cmd_name.c_str());
469 private:
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;
480 #pragma mark CommandObjectTargetList
482 class CommandObjectTargetList : public CommandObjectParsed {
483 public:
484 CommandObjectTargetList(CommandInterpreter &interpreter)
485 : CommandObjectParsed(
486 interpreter, "target list",
487 "List all current targets in the current debug session.", nullptr) {
490 ~CommandObjectTargetList() override = default;
492 protected:
493 void DoExecute(Args &args, CommandReturnObject &result) override {
494 Stream &strm = result.GetOutputStream();
496 bool show_stopped_process_status = false;
497 if (DumpTargetList(GetDebugger().GetTargetList(),
498 show_stopped_process_status, strm) == 0) {
499 strm.PutCString("No targets.\n");
501 result.SetStatus(eReturnStatusSuccessFinishResult);
505 #pragma mark CommandObjectTargetSelect
507 class CommandObjectTargetSelect : public CommandObjectParsed {
508 public:
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({target_arg});
517 ~CommandObjectTargetSelect() override = default;
519 protected:
520 void DoExecute(Args &args, CommandReturnObject &result) override {
521 if (args.GetArgumentCount() == 1) {
522 const char *target_identifier = args.GetArgumentAtIndex(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(target_identifier, 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 "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 "index %u is out of range since there are no active targets\n",
541 target_idx);
544 } else {
545 for (size_t i = 0; i < num_targets; i++) {
546 if (TargetSP target_sp = target_list.GetTargetAtIndex(i)) {
547 const std::string &label = target_sp->GetLabel();
548 if (!label.empty() && label == target_identifier) {
549 target_idx = i;
550 break;
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("invalid index string value '%s'\n",
563 target_identifier);
566 } else {
567 result.AppendError(
568 "'target select' takes a single argument: a target index\n");
573 #pragma mark CommandObjectTargetDelete
575 class CommandObjectTargetDelete : public CommandObjectParsed {
576 public:
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(&m_all_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
594 m_option_group.Append(&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({target_arg});
600 ~CommandObjectTargetDelete() override = default;
602 Options *GetOptions() override { return &m_option_group; }
604 protected:
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;
611 if (m_all_option.GetOptionValue()) {
612 for (size_t i = 0; i < target_list.GetNumTargets(); ++i)
613 delete_target_list.push_back(target_list.GetTargetAtIndex(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("no targets to delete");
619 return;
622 for (auto &entry : args.entries()) {
623 uint32_t target_idx;
624 if (entry.ref().getAsInteger(0, target_idx)) {
625 result.AppendErrorWithFormat("invalid target index '%s'\n",
626 entry.c_str());
627 return;
629 if (target_idx < num_targets) {
630 target_sp = target_list.GetTargetAtIndex(target_idx);
631 if (target_sp) {
632 delete_target_list.push_back(target_sp);
633 continue;
636 if (num_targets > 1)
637 result.AppendErrorWithFormat("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 "target index %u is out of range, the only valid index is 0\n",
643 target_idx);
645 return;
647 } else {
648 target_sp = target_list.GetSelectedTarget();
649 if (!target_sp) {
650 result.AppendErrorWithFormat("no target is currently selected\n");
651 return;
653 delete_target_list.push_back(target_sp);
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();
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);
668 result.GetOutputStream().Printf("%u targets deleted.\n",
669 (uint32_t)num_targets_to_delete);
670 result.SetStatus(eReturnStatusSuccessFinishResult);
672 return;
675 OptionGroupOptions m_option_group;
676 OptionGroupBoolean m_all_option;
677 OptionGroupBoolean m_cleanup_option;
680 class CommandObjectTargetShowLaunchEnvironment : public CommandObjectParsed {
681 public:
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) {}
690 ~CommandObjectTargetShowLaunchEnvironment() override = default;
692 protected:
693 void DoExecute(Args &args, CommandReturnObject &result) override {
694 Target *target = m_exe_ctx.GetTargetPtr();
695 Environment env = target->GetEnvironment();
697 std::vector<Environment::value_type *> env_vector;
698 env_vector.reserve(env.size());
699 for (auto &KV : env)
700 env_vector.push_back(&KV);
701 std::sort(env_vector.begin(), env_vector.end(),
702 [](Environment::value_type *a, Environment::value_type *b) {
703 return a->first() < b->first();
706 auto &strm = result.GetOutputStream();
707 for (auto &KV : env_vector)
708 strm.Format("{0}={1}\n", KV->first(), KV->second);
710 result.SetStatus(eReturnStatusSuccessFinishResult);
714 #pragma mark CommandObjectTargetVariable
716 class CommandObjectTargetVariable : public CommandObjectParsed {
717 static const uint32_t SHORT_OPTION_FILE = 0x66696c65; // 'file'
718 static const uint32_t SHORT_OPTION_SHLB = 0x73686c62; // 'shlb'
720 public:
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;
742 // Define the first (and only) variant of this arg.
743 var_name_arg.arg_type = eArgTypeVarName;
744 var_name_arg.arg_repetition = eArgRepeatPlus;
746 // There is only one variant this argument could be; put it into the
747 // argument entry.
748 arg.push_back(var_name_arg);
750 // Push the data for the first argument into the m_arguments vector.
751 m_arguments.push_back(arg);
753 m_option_group.Append(&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
754 m_option_group.Append(&m_option_variable, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
755 m_option_group.Append(&m_option_format,
756 OptionGroupFormat::OPTION_GROUP_FORMAT |
757 OptionGroupFormat::OPTION_GROUP_GDB_FMT,
758 LLDB_OPT_SET_1);
759 m_option_group.Append(&m_option_compile_units, LLDB_OPT_SET_ALL,
760 LLDB_OPT_SET_1);
761 m_option_group.Append(&m_option_shared_libraries, LLDB_OPT_SET_ALL,
762 LLDB_OPT_SET_1);
763 m_option_group.Finalize();
766 ~CommandObjectTargetVariable() override = default;
768 void DumpValueObject(Stream &s, VariableSP &var_sp, ValueObjectSP &valobj_sp,
769 const char *root_name) {
770 DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions());
772 if (!valobj_sp->GetTargetSP()->GetDisplayRuntimeSupportValues() &&
773 valobj_sp->IsRuntimeSupportValue())
774 return;
776 switch (var_sp->GetScope()) {
777 case eValueTypeVariableGlobal:
778 if (m_option_variable.show_scope)
779 s.PutCString("GLOBAL: ");
780 break;
782 case eValueTypeVariableStatic:
783 if (m_option_variable.show_scope)
784 s.PutCString("STATIC: ");
785 break;
787 case eValueTypeVariableArgument:
788 if (m_option_variable.show_scope)
789 s.PutCString(" ARG: ");
790 break;
792 case eValueTypeVariableLocal:
793 if (m_option_variable.show_scope)
794 s.PutCString(" LOCAL: ");
795 break;
797 case eValueTypeVariableThreadLocal:
798 if (m_option_variable.show_scope)
799 s.PutCString("THREAD: ");
800 break;
802 default:
803 break;
806 if (m_option_variable.show_decl) {
807 bool show_fullpaths = false;
808 bool show_module = true;
809 if (var_sp->DumpDeclaration(&s, show_fullpaths, show_module))
810 s.PutCString(": ");
813 const Format format = m_option_format.GetFormat();
814 if (format != eFormatDefault)
815 options.SetFormat(format);
817 options.SetRootValueObjectName(root_name);
819 valobj_sp->Dump(s, options);
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(ConstString(name), UINT32_MAX,
828 variable_list);
829 return variable_list.GetSize() - old_size;
832 Options *GetOptions() override { return &m_option_group; }
834 protected:
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("Global variables for {0} in {1}:\n",
843 sc.comp_unit->GetPrimaryFile(), sc.module_sp->GetFileSpec());
844 } else {
845 s.Printf("Global variables for %s\n",
846 sc.module_sp->GetFileSpec().GetPath().c_str());
848 } else if (sc.comp_unit) {
849 s.Format("Global variables for {0}\n", sc.comp_unit->GetPrimaryFile());
852 for (VariableSP var_sp : variable_list) {
853 if (!var_sp)
854 continue;
855 ValueObjectSP valobj_sp(ValueObjectVariable::Create(
856 exe_ctx.GetBestExecutionContextScope(), var_sp));
858 if (valobj_sp)
859 DumpValueObject(s, var_sp, valobj_sp, var_sp->GetName().GetCString());
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();
868 if (argc > 0) {
869 for (const Args::ArgEntry &arg : args) {
870 VariableList variable_list;
871 ValueObjectList valobj_list;
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 "error: invalid regular expression: '%s'\n", arg.c_str());
880 return;
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 arg.c_str(), m_exe_ctx.GetBestExecutionContextScope(),
889 GetVariableCallback, target, variable_list, valobj_list));
890 matches = variable_list.GetSize();
893 if (matches == 0) {
894 result.AppendErrorWithFormat("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(global_idx));
900 if (var_sp) {
901 ValueObjectSP valobj_sp(
902 valobj_list.GetValueObjectAtIndex(global_idx));
903 if (!valobj_sp)
904 valobj_sp = ValueObjectVariable::Create(
905 m_exe_ctx.GetBestExecutionContextScope(), var_sp);
907 if (valobj_sp)
908 DumpValueObject(s, var_sp, valobj_sp,
909 use_var_name ? var_sp->GetName().GetCString()
910 : arg.c_str());
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(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(m_exe_ctx, sc, *comp_unit_varlist_sp, s);
938 success = true;
943 if (!success) {
944 if (frame) {
945 if (comp_unit)
946 result.AppendErrorWithFormatv(
947 "no global variables in current compile unit: {0}\n",
948 comp_unit->GetPrimaryFile());
949 else
950 result.AppendErrorWithFormat(
951 "no debug information for frame %u\n",
952 frame->GetFrameIndex());
953 } else
954 result.AppendError("'target variable' takes one or more global "
955 "variable names as arguments\n");
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(shlib_idx));
963 ModuleSpec module_spec(module_file);
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 compile_units.GetFileSpecAtIndex(cu_idx), sc_list);
972 } else {
973 SymbolContext sc;
974 sc.module_sp = module_sp;
975 sc_list.Append(sc);
977 } else {
978 // Didn't find matching shlib/module in target...
979 result.AppendErrorWithFormat(
980 "target doesn't contain the specified shared library: %s\n",
981 module_file.GetPath().c_str());
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 compile_units.GetFileSpecAtIndex(cu_idx), sc_list);
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(m_exe_ctx, sc, *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(all_globals_regex, UINT32_MAX,
1005 variable_list);
1006 DumpGlobalVariableList(m_exe_ctx, sc, variable_list, s);
1012 m_interpreter.PrintWarningsIfNecessary(result.GetOutputStream(),
1013 m_cmd_name);
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;
1024 #pragma mark CommandObjectTargetModulesSearchPathsAdd
1026 class CommandObjectTargetModulesSearchPathsAdd : public CommandObjectParsed {
1027 public:
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;
1037 // Define the first variant of this arg pair.
1038 old_prefix_arg.arg_type = eArgTypeOldPathPrefix;
1039 old_prefix_arg.arg_repetition = eArgRepeatPairPlus;
1041 // Define the first variant of this arg pair.
1042 new_prefix_arg.arg_type = eArgTypeNewPathPrefix;
1043 new_prefix_arg.arg_repetition = eArgRepeatPairPlus;
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...
1051 arg.push_back(old_prefix_arg);
1052 arg.push_back(new_prefix_arg);
1054 m_arguments.push_back(arg);
1057 ~CommandObjectTargetModulesSearchPathsAdd() override = default;
1059 protected:
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("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(i);
1068 const char *to = command.GetArgumentAtIndex(i + 1);
1070 if (from[0] && to[0]) {
1071 Log *log = GetLog(LLDBLog::Host);
1072 if (log) {
1073 LLDB_LOGF(log,
1074 "target modules search path adding ImageSearchPath "
1075 "pair: '%s' -> '%s'",
1076 from, to);
1078 bool last_pair = ((argc - i) == 2);
1079 target->GetImageSearchPathList().Append(
1080 from, to, last_pair); // Notify if this is the last pair
1081 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1082 } else {
1083 if (from[0])
1084 result.AppendError("<path-prefix> can't be empty\n");
1085 else
1086 result.AppendError("<new-path-prefix> can't be empty\n");
1093 #pragma mark CommandObjectTargetModulesSearchPathsClear
1095 class CommandObjectTargetModulesSearchPathsClear : public CommandObjectParsed {
1096 public:
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) {}
1104 ~CommandObjectTargetModulesSearchPathsClear() override = default;
1106 protected:
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);
1115 #pragma mark CommandObjectTargetModulesSearchPathsInsert
1117 class CommandObjectTargetModulesSearchPathsInsert : public CommandObjectParsed {
1118 public:
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;
1130 // Define the first and only variant of this arg.
1131 index_arg.arg_type = eArgTypeIndex;
1132 index_arg.arg_repetition = eArgRepeatPlain;
1134 // Put the one and only variant into the first arg for m_arguments:
1135 arg1.push_back(index_arg);
1137 // Define the first variant of this arg pair.
1138 old_prefix_arg.arg_type = eArgTypeOldPathPrefix;
1139 old_prefix_arg.arg_repetition = eArgRepeatPairPlus;
1141 // Define the first variant of this arg pair.
1142 new_prefix_arg.arg_type = eArgTypeNewPathPrefix;
1143 new_prefix_arg.arg_repetition = eArgRepeatPairPlus;
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...
1151 arg2.push_back(old_prefix_arg);
1152 arg2.push_back(new_prefix_arg);
1154 // Add arguments to m_arguments.
1155 m_arguments.push_back(arg1);
1156 m_arguments.push_back(arg2);
1159 ~CommandObjectTargetModulesSearchPathsInsert() override = default;
1161 void
1162 HandleArgumentCompletion(CompletionRequest &request,
1163 OptionElementVector &opt_element_vector) override {
1164 if (!m_exe_ctx.HasTargetScope() || request.GetCursorIndex() != 0)
1165 return;
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(i, old_path, new_path))
1173 break;
1174 StreamString strm;
1175 strm << old_path << " -> " << new_path;
1176 request.TryCompleteCurrentArg(std::to_string(i), strm.GetString());
1180 protected:
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;
1188 if (!llvm::to_integer(command.GetArgumentAtIndex(0), insert_idx)) {
1189 result.AppendErrorWithFormat(
1190 "<index> parameter is not an integer: '%s'.\n",
1191 command.GetArgumentAtIndex(0));
1192 return;
1195 // shift off the index
1196 command.Shift();
1197 argc = command.GetArgumentCount();
1199 for (uint32_t i = 0; i < argc; i += 2, ++insert_idx) {
1200 const char *from = command.GetArgumentAtIndex(i);
1201 const char *to = command.GetArgumentAtIndex(i + 1);
1203 if (from[0] && to[0]) {
1204 bool last_pair = ((argc - i) == 2);
1205 target->GetImageSearchPathList().Insert(from, to, insert_idx,
1206 last_pair);
1207 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1208 } else {
1209 if (from[0])
1210 result.AppendError("<path-prefix> can't be empty\n");
1211 else
1212 result.AppendError("<new-path-prefix> can't be empty\n");
1213 return;
1216 } else {
1217 result.AppendError("insert requires at least three arguments\n");
1222 #pragma mark CommandObjectTargetModulesSearchPathsList
1224 class CommandObjectTargetModulesSearchPathsList : public CommandObjectParsed {
1225 public:
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) {}
1233 ~CommandObjectTargetModulesSearchPathsList() override = default;
1235 protected:
1236 void DoExecute(Args &command, CommandReturnObject &result) override {
1237 Target *target = &GetSelectedTarget();
1239 target->GetImageSearchPathList().Dump(&result.GetOutputStream());
1240 result.SetStatus(eReturnStatusSuccessFinishResult);
1244 #pragma mark CommandObjectTargetModulesSearchPathsQuery
1246 class CommandObjectTargetModulesSearchPathsQuery : public CommandObjectParsed {
1247 public:
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;
1256 // Define the first (and only) variant of this arg.
1257 path_arg.arg_type = eArgTypeDirectoryName;
1258 path_arg.arg_repetition = eArgRepeatPlain;
1260 // There is only one variant this argument could be; put it into the
1261 // argument entry.
1262 arg.push_back(path_arg);
1264 // Push the data for the first argument into the m_arguments vector.
1265 m_arguments.push_back(arg);
1268 ~CommandObjectTargetModulesSearchPathsQuery() override = default;
1270 protected:
1271 void DoExecute(Args &command, CommandReturnObject &result) override {
1272 Target *target = &GetSelectedTarget();
1273 if (command.GetArgumentCount() != 1) {
1274 result.AppendError("query requires one argument\n");
1275 return;
1278 ConstString orig(command.GetArgumentAtIndex(0));
1279 ConstString transformed;
1280 if (target->GetImageSearchPathList().RemapPath(orig, transformed))
1281 result.GetOutputStream().Printf("%s\n", transformed.GetCString());
1282 else
1283 result.GetOutputStream().Printf("%s\n", orig.GetCString());
1285 result.SetStatus(eReturnStatusSuccessFinishResult);
1289 // Static Helper functions
1290 static void DumpModuleArchitecture(Stream &strm, Module *module,
1291 bool full_triple, uint32_t width) {
1292 if (module) {
1293 StreamString arch_strm;
1295 if (full_triple)
1296 module->GetArchitecture().DumpTriple(arch_strm.AsRawOstream());
1297 else
1298 arch_strm.PutCString(module->GetArchitecture().GetArchitectureName());
1299 std::string arch_str = std::string(arch_strm.GetString());
1301 if (width)
1302 strm.Printf("%-*s", width, arch_str.c_str());
1303 else
1304 strm.PutCString(arch_str);
1308 static void DumpModuleUUID(Stream &strm, Module *module) {
1309 if (module && module->GetUUID().IsValid())
1310 module->GetUUID().Dump(strm);
1311 else
1312 strm.PutCString(" ");
1315 static 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, 0, false, eSymbolContextCompUnit, sc_list);
1325 bool first_module = true;
1326 for (const SymbolContext &sc : sc_list) {
1327 if (!first_module)
1328 strm << "\n\n";
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 &strm, interpreter.GetExecutionContext().GetTargetPtr(),
1336 desc_level);
1337 else
1338 strm << "No line table";
1340 first_module = false;
1343 return num_matches;
1346 static 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("%-*s", width, fullpath.c_str());
1352 return;
1353 } else {
1354 file_spec_ptr->Dump(strm.AsRawOstream());
1355 return;
1358 // Keep the width spacing correct if things go wrong...
1359 if (width > 0)
1360 strm.Printf("%-*s", width, "");
1363 static 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("%-*s", width, file_spec_ptr->GetDirectory().AsCString(""));
1368 else
1369 file_spec_ptr->GetDirectory().Dump(&strm);
1370 return;
1372 // Keep the width spacing correct if things go wrong...
1373 if (width > 0)
1374 strm.Printf("%-*s", width, "");
1377 static 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("%-*s", width, file_spec_ptr->GetFilename().AsCString(""));
1382 else
1383 file_spec_ptr->GetFilename().Dump(&strm);
1384 return;
1386 // Keep the width spacing correct if things go wrong...
1387 if (width > 0)
1388 strm.Printf("%-*s", width, "");
1391 static 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;
1397 size_t num_dumped = 0;
1398 strm.Format("Dumping headers for {0} module(s).\n", 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();
1406 ObjectFile *objfile = module_sp->GetObjectFile();
1407 if (objfile)
1408 objfile->Dump(&strm);
1409 else {
1410 strm.Format("No object file for module: {0:F}\n",
1411 module_sp->GetFileSpec());
1415 strm.IndentLess();
1416 return num_dumped;
1419 static 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(&strm, interpreter.GetExecutionContext().GetTargetPtr(),
1426 sort_order, name_preference);
1429 static 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("Sections for '%s' (%s):\n",
1435 module->GetSpecificationDescription().c_str(),
1436 module->GetArchitecture().GetArchitectureName());
1437 section_list->Dump(strm.AsRawOstream(), strm.GetIndentLevel() + 2,
1438 interpreter.GetExecutionContext().GetTargetPtr(), true,
1439 UINT32_MAX);
1444 static bool DumpModuleSymbolFile(Stream &strm, Module *module) {
1445 if (module) {
1446 if (SymbolFile *symbol_file = module->GetSymbolFile(true)) {
1447 symbol_file->Dump(strm);
1448 return true;
1451 return false;
1454 static bool GetSeparateDebugInfoList(StructuredData::Array &list,
1455 Module *module) {
1456 if (module) {
1457 if (SymbolFile *symbol_file = module->GetSymbolFile(/*can_create=*/true)) {
1458 StructuredData::Dictionary d;
1459 if (symbol_file->GetSeparateDebugInfo(d)) {
1460 list.AddItem(
1461 std::make_shared<StructuredData::Dictionary>(std::move(d)));
1462 return true;
1466 return false;
1469 static void DumpDwoFilesTable(Stream &strm,
1470 StructuredData::Array &dwo_listings) {
1471 strm.PutCString("Dwo ID Err Dwo Path");
1472 strm.EOL();
1473 strm.PutCString(
1474 "------------------ --- -----------------------------------------");
1475 strm.EOL();
1476 dwo_listings.ForEach([&strm](StructuredData::Object *dwo) {
1477 StructuredData::Dictionary *dict = dwo->GetAsDictionary();
1478 if (!dict)
1479 return false;
1481 uint64_t dwo_id;
1482 if (dict->GetValueForKeyAsInteger("dwo_id", dwo_id))
1483 strm.Printf("0x%16.16" PRIx64 " ", dwo_id);
1484 else
1485 strm.Printf("0x???????????????? ");
1487 llvm::StringRef error;
1488 if (dict->GetValueForKeyAsString("error", error))
1489 strm << "E " << error;
1490 else {
1491 llvm::StringRef resolved_dwo_path;
1492 if (dict->GetValueForKeyAsString("resolved_dwo_path",
1493 resolved_dwo_path)) {
1494 strm << " " << resolved_dwo_path;
1495 if (resolved_dwo_path.ends_with(".dwp")) {
1496 llvm::StringRef dwo_name;
1497 if (dict->GetValueForKeyAsString("dwo_name", dwo_name))
1498 strm << "(" << dwo_name << ")";
1502 strm.EOL();
1503 return true;
1507 static void DumpOsoFilesTable(Stream &strm,
1508 StructuredData::Array &oso_listings) {
1509 strm.PutCString("Mod Time Err Oso Path");
1510 strm.EOL();
1511 strm.PutCString("------------------ --- ---------------------");
1512 strm.EOL();
1513 oso_listings.ForEach([&strm](StructuredData::Object *oso) {
1514 StructuredData::Dictionary *dict = oso->GetAsDictionary();
1515 if (!dict)
1516 return false;
1518 uint32_t oso_mod_time;
1519 if (dict->GetValueForKeyAsInteger("oso_mod_time", oso_mod_time))
1520 strm.Printf("0x%16.16" PRIx32 " ", oso_mod_time);
1522 llvm::StringRef error;
1523 if (dict->GetValueForKeyAsString("error", error))
1524 strm << "E " << error;
1525 else {
1526 llvm::StringRef oso_path;
1527 if (dict->GetValueForKeyAsString("oso_path", oso_path))
1528 strm << " " << oso_path;
1530 strm.EOL();
1531 return true;
1535 static void DumpAddress(ExecutionContextScope *exe_scope,
1536 const Address &so_addr, bool verbose, bool all_ranges,
1537 Stream &strm) {
1538 strm.IndentMore();
1539 strm.Indent(" Address: ");
1540 so_addr.Dump(&strm, exe_scope, Address::DumpStyleModuleWithFileAddress);
1541 strm.PutCString(" (");
1542 so_addr.Dump(&strm, exe_scope, Address::DumpStyleSectionNameOffset);
1543 strm.PutCString(")\n");
1544 strm.Indent(" Summary: ");
1545 const uint32_t save_indent = strm.GetIndentLevel();
1546 strm.SetIndentLevel(save_indent + 13);
1547 so_addr.Dump(&strm, exe_scope, Address::DumpStyleResolvedDescription);
1548 strm.SetIndentLevel(save_indent);
1549 // Print out detailed address information when verbose is enabled
1550 if (verbose) {
1551 strm.EOL();
1552 so_addr.Dump(&strm, exe_scope, Address::DumpStyleDetailedSymbolContext,
1553 Address::DumpStyleInvalid, UINT32_MAX, all_ranges);
1555 strm.IndentLess();
1558 static bool LookupAddressInModule(CommandInterpreter &interpreter, Stream &strm,
1559 Module *module, uint32_t resolve_mask,
1560 lldb::addr_t raw_addr, lldb::addr_t offset,
1561 bool verbose, bool all_ranges) {
1562 if (module) {
1563 lldb::addr_t addr = raw_addr - offset;
1564 Address so_addr;
1565 SymbolContext sc;
1566 Target *target = interpreter.GetExecutionContext().GetTargetPtr();
1567 if (target && !target->GetSectionLoadList().IsEmpty()) {
1568 if (!target->GetSectionLoadList().ResolveLoadAddress(addr, so_addr))
1569 return false;
1570 else if (so_addr.GetModule().get() != module)
1571 return false;
1572 } else {
1573 if (!module->ResolveFileAddress(addr, so_addr))
1574 return false;
1577 ExecutionContextScope *exe_scope =
1578 interpreter.GetExecutionContext().GetBestExecutionContextScope();
1579 DumpAddress(exe_scope, so_addr, verbose, all_ranges, strm);
1580 return true;
1583 return false;
1586 static uint32_t LookupSymbolInModule(CommandInterpreter &interpreter,
1587 Stream &strm, Module *module,
1588 const char *name, bool name_is_regex,
1589 bool verbose, bool all_ranges) {
1590 if (!module)
1591 return 0;
1593 Symtab *symtab = module->GetSymtab();
1594 if (!symtab)
1595 return 0;
1597 SymbolContext sc;
1598 std::vector<uint32_t> match_indexes;
1599 ConstString symbol_name(name);
1600 uint32_t num_matches = 0;
1601 if (name_is_regex) {
1602 RegularExpression name_regexp(symbol_name.GetStringRef());
1603 num_matches = symtab->AppendSymbolIndexesMatchingRegExAndType(
1604 name_regexp, eSymbolTypeAny, match_indexes);
1605 } else {
1606 num_matches =
1607 symtab->AppendSymbolIndexesWithName(symbol_name, match_indexes);
1610 if (num_matches > 0) {
1611 strm.Indent();
1612 strm.Printf("%u symbols match %s'%s' in ", num_matches,
1613 name_is_regex ? "the regular expression " : "", name);
1614 DumpFullpath(strm, &module->GetFileSpec(), 0);
1615 strm.PutCString(":\n");
1616 strm.IndentMore();
1617 for (uint32_t i = 0; i < num_matches; ++i) {
1618 Symbol *symbol = symtab->SymbolAtIndex(match_indexes[i]);
1619 if (symbol) {
1620 if (symbol->ValueIsAddress()) {
1621 DumpAddress(
1622 interpreter.GetExecutionContext().GetBestExecutionContextScope(),
1623 symbol->GetAddressRef(), verbose, all_ranges, strm);
1624 strm.EOL();
1625 } else {
1626 strm.IndentMore();
1627 strm.Indent(" Name: ");
1628 strm.PutCString(symbol->GetDisplayName().GetStringRef());
1629 strm.EOL();
1630 strm.Indent(" Value: ");
1631 strm.Printf("0x%16.16" PRIx64 "\n", symbol->GetRawValue());
1632 if (symbol->GetByteSizeIsValid()) {
1633 strm.Indent(" Size: ");
1634 strm.Printf("0x%16.16" PRIx64 "\n", symbol->GetByteSize());
1636 strm.IndentLess();
1640 strm.IndentLess();
1642 return num_matches;
1645 static void DumpSymbolContextList(ExecutionContextScope *exe_scope,
1646 Stream &strm,
1647 const SymbolContextList &sc_list,
1648 bool verbose, bool all_ranges) {
1649 strm.IndentMore();
1650 bool first_module = true;
1651 for (const SymbolContext &sc : sc_list) {
1652 if (!first_module)
1653 strm.EOL();
1655 AddressRange range;
1657 sc.GetAddressRange(eSymbolContextEverything, 0, true, range);
1659 DumpAddress(exe_scope, range.GetBaseAddress(), verbose, all_ranges, strm);
1660 first_module = false;
1662 strm.IndentLess();
1665 static size_t LookupFunctionInModule(CommandInterpreter &interpreter,
1666 Stream &strm, Module *module,
1667 const char *name, bool name_is_regex,
1668 const ModuleFunctionSearchOptions &options,
1669 bool verbose, bool all_ranges) {
1670 if (module && name && name[0]) {
1671 SymbolContextList sc_list;
1672 size_t num_matches = 0;
1673 if (name_is_regex) {
1674 RegularExpression function_name_regex((llvm::StringRef(name)));
1675 module->FindFunctions(function_name_regex, options, sc_list);
1676 } else {
1677 ConstString function_name(name);
1678 module->FindFunctions(function_name, CompilerDeclContext(),
1679 eFunctionNameTypeAuto, options, sc_list);
1681 num_matches = sc_list.GetSize();
1682 if (num_matches) {
1683 strm.Indent();
1684 strm.Printf("%" PRIu64 " match%s found in ", (uint64_t)num_matches,
1685 num_matches > 1 ? "es" : "");
1686 DumpFullpath(strm, &module->GetFileSpec(), 0);
1687 strm.PutCString(":\n");
1688 DumpSymbolContextList(
1689 interpreter.GetExecutionContext().GetBestExecutionContextScope(),
1690 strm, sc_list, verbose, all_ranges);
1692 return num_matches;
1694 return 0;
1697 static size_t LookupTypeInModule(Target *target,
1698 CommandInterpreter &interpreter, Stream &strm,
1699 Module *module, const char *name_cstr,
1700 bool name_is_regex) {
1701 TypeList type_list;
1702 if (module && name_cstr && name_cstr[0]) {
1703 const uint32_t max_num_matches = UINT32_MAX;
1704 bool name_is_fully_qualified = false;
1706 ConstString name(name_cstr);
1707 llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files;
1708 module->FindTypes(name, name_is_fully_qualified, max_num_matches,
1709 searched_symbol_files, type_list);
1711 if (type_list.Empty())
1712 return 0;
1714 const uint64_t num_matches = type_list.GetSize();
1716 strm.Indent();
1717 strm.Printf("%" PRIu64 " match%s found in ", num_matches,
1718 num_matches > 1 ? "es" : "");
1719 DumpFullpath(strm, &module->GetFileSpec(), 0);
1720 strm.PutCString(":\n");
1721 for (TypeSP type_sp : type_list.Types()) {
1722 if (!type_sp)
1723 continue;
1724 // Resolve the clang type so that any forward references to types
1725 // that haven't yet been parsed will get parsed.
1726 type_sp->GetFullCompilerType();
1727 type_sp->GetDescription(&strm, eDescriptionLevelFull, true, target);
1728 // Print all typedef chains
1729 TypeSP typedef_type_sp(type_sp);
1730 TypeSP typedefed_type_sp(typedef_type_sp->GetTypedefType());
1731 while (typedefed_type_sp) {
1732 strm.EOL();
1733 strm.Printf(" typedef '%s': ",
1734 typedef_type_sp->GetName().GetCString());
1735 typedefed_type_sp->GetFullCompilerType();
1736 typedefed_type_sp->GetDescription(&strm, eDescriptionLevelFull, true,
1737 target);
1738 typedef_type_sp = typedefed_type_sp;
1739 typedefed_type_sp = typedef_type_sp->GetTypedefType();
1741 strm.EOL();
1744 return type_list.GetSize();
1747 static size_t LookupTypeHere(Target *target, CommandInterpreter &interpreter,
1748 Stream &strm, Module &module,
1749 const char *name_cstr, bool name_is_regex) {
1750 TypeList type_list;
1751 const uint32_t max_num_matches = UINT32_MAX;
1752 bool name_is_fully_qualified = false;
1754 ConstString name(name_cstr);
1755 llvm::DenseSet<SymbolFile *> searched_symbol_files;
1756 module.FindTypes(name, name_is_fully_qualified, max_num_matches,
1757 searched_symbol_files, type_list);
1759 if (type_list.Empty())
1760 return 0;
1762 strm.Indent();
1763 strm.PutCString("Best match found in ");
1764 DumpFullpath(strm, &module.GetFileSpec(), 0);
1765 strm.PutCString(":\n");
1767 TypeSP type_sp(type_list.GetTypeAtIndex(0));
1768 if (type_sp) {
1769 // Resolve the clang type so that any forward references to types that
1770 // haven't yet been parsed will get parsed.
1771 type_sp->GetFullCompilerType();
1772 type_sp->GetDescription(&strm, eDescriptionLevelFull, true, target);
1773 // Print all typedef chains.
1774 TypeSP typedef_type_sp(type_sp);
1775 TypeSP typedefed_type_sp(typedef_type_sp->GetTypedefType());
1776 while (typedefed_type_sp) {
1777 strm.EOL();
1778 strm.Printf(" typedef '%s': ",
1779 typedef_type_sp->GetName().GetCString());
1780 typedefed_type_sp->GetFullCompilerType();
1781 typedefed_type_sp->GetDescription(&strm, eDescriptionLevelFull, true,
1782 target);
1783 typedef_type_sp = typedefed_type_sp;
1784 typedefed_type_sp = typedef_type_sp->GetTypedefType();
1787 strm.EOL();
1788 return type_list.GetSize();
1791 static uint32_t LookupFileAndLineInModule(CommandInterpreter &interpreter,
1792 Stream &strm, Module *module,
1793 const FileSpec &file_spec,
1794 uint32_t line, bool check_inlines,
1795 bool verbose, bool all_ranges) {
1796 if (module && file_spec) {
1797 SymbolContextList sc_list;
1798 const uint32_t num_matches = module->ResolveSymbolContextsForFileSpec(
1799 file_spec, line, check_inlines, eSymbolContextEverything, sc_list);
1800 if (num_matches > 0) {
1801 strm.Indent();
1802 strm.Printf("%u match%s found in ", num_matches,
1803 num_matches > 1 ? "es" : "");
1804 strm << file_spec;
1805 if (line > 0)
1806 strm.Printf(":%u", line);
1807 strm << " in ";
1808 DumpFullpath(strm, &module->GetFileSpec(), 0);
1809 strm.PutCString(":\n");
1810 DumpSymbolContextList(
1811 interpreter.GetExecutionContext().GetBestExecutionContextScope(),
1812 strm, sc_list, verbose, all_ranges);
1813 return num_matches;
1816 return 0;
1819 static size_t FindModulesByName(Target *target, const char *module_name,
1820 ModuleList &module_list,
1821 bool check_global_list) {
1822 FileSpec module_file_spec(module_name);
1823 ModuleSpec module_spec(module_file_spec);
1825 const size_t initial_size = module_list.GetSize();
1827 if (check_global_list) {
1828 // Check the global list
1829 std::lock_guard<std::recursive_mutex> guard(
1830 Module::GetAllocationModuleCollectionMutex());
1831 const size_t num_modules = Module::GetNumberAllocatedModules();
1832 ModuleSP module_sp;
1833 for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
1834 Module *module = Module::GetAllocatedModuleAtIndex(image_idx);
1836 if (module) {
1837 if (module->MatchesModuleSpec(module_spec)) {
1838 module_sp = module->shared_from_this();
1839 module_list.AppendIfNeeded(module_sp);
1843 } else {
1844 if (target) {
1845 target->GetImages().FindModules(module_spec, module_list);
1846 const size_t num_matches = module_list.GetSize();
1848 // Not found in our module list for our target, check the main shared
1849 // module list in case it is a extra file used somewhere else
1850 if (num_matches == 0) {
1851 module_spec.GetArchitecture() = target->GetArchitecture();
1852 ModuleList::FindSharedModules(module_spec, module_list);
1854 } else {
1855 ModuleList::FindSharedModules(module_spec, module_list);
1859 return module_list.GetSize() - initial_size;
1862 #pragma mark CommandObjectTargetModulesModuleAutoComplete
1864 // A base command object class that can auto complete with module file
1865 // paths
1867 class CommandObjectTargetModulesModuleAutoComplete
1868 : public CommandObjectParsed {
1869 public:
1870 CommandObjectTargetModulesModuleAutoComplete(CommandInterpreter &interpreter,
1871 const char *name,
1872 const char *help,
1873 const char *syntax,
1874 uint32_t flags = 0)
1875 : CommandObjectParsed(interpreter, name, help, syntax, flags) {
1876 CommandArgumentEntry arg;
1877 CommandArgumentData file_arg;
1879 // Define the first (and only) variant of this arg.
1880 file_arg.arg_type = eArgTypeFilename;
1881 file_arg.arg_repetition = eArgRepeatStar;
1883 // There is only one variant this argument could be; put it into the
1884 // argument entry.
1885 arg.push_back(file_arg);
1887 // Push the data for the first argument into the m_arguments vector.
1888 m_arguments.push_back(arg);
1891 ~CommandObjectTargetModulesModuleAutoComplete() override = default;
1893 void
1894 HandleArgumentCompletion(CompletionRequest &request,
1895 OptionElementVector &opt_element_vector) override {
1896 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1897 GetCommandInterpreter(), lldb::eModuleCompletion, request, nullptr);
1901 #pragma mark CommandObjectTargetModulesSourceFileAutoComplete
1903 // A base command object class that can auto complete with module source
1904 // file paths
1906 class CommandObjectTargetModulesSourceFileAutoComplete
1907 : public CommandObjectParsed {
1908 public:
1909 CommandObjectTargetModulesSourceFileAutoComplete(
1910 CommandInterpreter &interpreter, const char *name, const char *help,
1911 const char *syntax, uint32_t flags)
1912 : CommandObjectParsed(interpreter, name, help, syntax, flags) {
1913 CommandArgumentEntry arg;
1914 CommandArgumentData source_file_arg;
1916 // Define the first (and only) variant of this arg.
1917 source_file_arg.arg_type = eArgTypeSourceFile;
1918 source_file_arg.arg_repetition = eArgRepeatPlus;
1920 // There is only one variant this argument could be; put it into the
1921 // argument entry.
1922 arg.push_back(source_file_arg);
1924 // Push the data for the first argument into the m_arguments vector.
1925 m_arguments.push_back(arg);
1928 ~CommandObjectTargetModulesSourceFileAutoComplete() override = default;
1930 void
1931 HandleArgumentCompletion(CompletionRequest &request,
1932 OptionElementVector &opt_element_vector) override {
1933 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1934 GetCommandInterpreter(), lldb::eSourceFileCompletion, request, nullptr);
1938 #pragma mark CommandObjectTargetModulesDumpObjfile
1940 class CommandObjectTargetModulesDumpObjfile
1941 : public CommandObjectTargetModulesModuleAutoComplete {
1942 public:
1943 CommandObjectTargetModulesDumpObjfile(CommandInterpreter &interpreter)
1944 : CommandObjectTargetModulesModuleAutoComplete(
1945 interpreter, "target modules dump objfile",
1946 "Dump the object file headers from one or more target modules.",
1947 nullptr, eCommandRequiresTarget) {}
1949 ~CommandObjectTargetModulesDumpObjfile() override = default;
1951 protected:
1952 void DoExecute(Args &command, CommandReturnObject &result) override {
1953 Target *target = &GetSelectedTarget();
1955 uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
1956 result.GetOutputStream().SetAddressByteSize(addr_byte_size);
1957 result.GetErrorStream().SetAddressByteSize(addr_byte_size);
1959 size_t num_dumped = 0;
1960 if (command.GetArgumentCount() == 0) {
1961 // Dump all headers for all modules images
1962 num_dumped = DumpModuleObjfileHeaders(result.GetOutputStream(),
1963 target->GetImages());
1964 if (num_dumped == 0) {
1965 result.AppendError("the target has no associated executable images");
1967 } else {
1968 // Find the modules that match the basename or full path.
1969 ModuleList module_list;
1970 const char *arg_cstr;
1971 for (int arg_idx = 0;
1972 (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
1973 ++arg_idx) {
1974 size_t num_matched =
1975 FindModulesByName(target, arg_cstr, module_list, true);
1976 if (num_matched == 0) {
1977 result.AppendWarningWithFormat(
1978 "Unable to find an image that matches '%s'.\n", arg_cstr);
1981 // Dump all the modules we found.
1982 num_dumped =
1983 DumpModuleObjfileHeaders(result.GetOutputStream(), module_list);
1986 if (num_dumped > 0) {
1987 result.SetStatus(eReturnStatusSuccessFinishResult);
1988 } else {
1989 result.AppendError("no matching executable images found");
1994 #define LLDB_OPTIONS_target_modules_dump_symtab
1995 #include "CommandOptions.inc"
1997 class CommandObjectTargetModulesDumpSymtab
1998 : public CommandObjectTargetModulesModuleAutoComplete {
1999 public:
2000 CommandObjectTargetModulesDumpSymtab(CommandInterpreter &interpreter)
2001 : CommandObjectTargetModulesModuleAutoComplete(
2002 interpreter, "target modules dump symtab",
2003 "Dump the symbol table from one or more target modules.", nullptr,
2004 eCommandRequiresTarget) {}
2006 ~CommandObjectTargetModulesDumpSymtab() override = default;
2008 Options *GetOptions() override { return &m_options; }
2010 class CommandOptions : public Options {
2011 public:
2012 CommandOptions() = default;
2014 ~CommandOptions() override = default;
2016 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2017 ExecutionContext *execution_context) override {
2018 Status error;
2019 const int short_option = m_getopt_table[option_idx].val;
2021 switch (short_option) {
2022 case 'm':
2023 m_prefer_mangled.SetCurrentValue(true);
2024 m_prefer_mangled.SetOptionWasSet();
2025 break;
2027 case 's':
2028 m_sort_order = (SortOrder)OptionArgParser::ToOptionEnum(
2029 option_arg, GetDefinitions()[option_idx].enum_values,
2030 eSortOrderNone, error);
2031 break;
2033 default:
2034 llvm_unreachable("Unimplemented option");
2036 return error;
2039 void OptionParsingStarting(ExecutionContext *execution_context) override {
2040 m_sort_order = eSortOrderNone;
2041 m_prefer_mangled.Clear();
2044 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2045 return llvm::ArrayRef(g_target_modules_dump_symtab_options);
2048 SortOrder m_sort_order = eSortOrderNone;
2049 OptionValueBoolean m_prefer_mangled = {false, false};
2052 protected:
2053 void DoExecute(Args &command, CommandReturnObject &result) override {
2054 Target *target = &GetSelectedTarget();
2055 uint32_t num_dumped = 0;
2056 Mangled::NamePreference name_preference =
2057 (m_options.m_prefer_mangled ? Mangled::ePreferMangled
2058 : Mangled::ePreferDemangled);
2060 uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
2061 result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2062 result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2064 if (command.GetArgumentCount() == 0) {
2065 // Dump all sections for all modules images
2066 const ModuleList &module_list = target->GetImages();
2067 std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex());
2068 const size_t num_modules = module_list.GetSize();
2069 if (num_modules > 0) {
2070 result.GetOutputStream().Format(
2071 "Dumping symbol table for {0} modules.\n", num_modules);
2072 for (ModuleSP module_sp : module_list.ModulesNoLocking()) {
2073 if (num_dumped > 0) {
2074 result.GetOutputStream().EOL();
2075 result.GetOutputStream().EOL();
2077 if (INTERRUPT_REQUESTED(GetDebugger(),
2078 "Interrupted in dump all symtabs with {0} "
2079 "of {1} dumped.", num_dumped, num_modules))
2080 break;
2082 num_dumped++;
2083 DumpModuleSymtab(m_interpreter, result.GetOutputStream(),
2084 module_sp.get(), m_options.m_sort_order,
2085 name_preference);
2087 } else {
2088 result.AppendError("the target has no associated executable images");
2089 return;
2091 } else {
2092 // Dump specified images (by basename or fullpath)
2093 const char *arg_cstr;
2094 for (int arg_idx = 0;
2095 (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
2096 ++arg_idx) {
2097 ModuleList module_list;
2098 const size_t num_matches =
2099 FindModulesByName(target, arg_cstr, module_list, true);
2100 if (num_matches > 0) {
2101 for (ModuleSP module_sp : module_list.Modules()) {
2102 if (module_sp) {
2103 if (num_dumped > 0) {
2104 result.GetOutputStream().EOL();
2105 result.GetOutputStream().EOL();
2107 if (INTERRUPT_REQUESTED(GetDebugger(),
2108 "Interrupted in dump symtab list with {0} of {1} dumped.",
2109 num_dumped, num_matches))
2110 break;
2112 num_dumped++;
2113 DumpModuleSymtab(m_interpreter, result.GetOutputStream(),
2114 module_sp.get(), m_options.m_sort_order,
2115 name_preference);
2118 } else
2119 result.AppendWarningWithFormat(
2120 "Unable to find an image that matches '%s'.\n", arg_cstr);
2124 if (num_dumped > 0)
2125 result.SetStatus(eReturnStatusSuccessFinishResult);
2126 else {
2127 result.AppendError("no matching executable images found");
2131 CommandOptions m_options;
2134 #pragma mark CommandObjectTargetModulesDumpSections
2136 // Image section dumping command
2138 class CommandObjectTargetModulesDumpSections
2139 : public CommandObjectTargetModulesModuleAutoComplete {
2140 public:
2141 CommandObjectTargetModulesDumpSections(CommandInterpreter &interpreter)
2142 : CommandObjectTargetModulesModuleAutoComplete(
2143 interpreter, "target modules dump sections",
2144 "Dump the sections from one or more target modules.",
2145 //"target modules dump sections [<file1> ...]")
2146 nullptr, eCommandRequiresTarget) {}
2148 ~CommandObjectTargetModulesDumpSections() override = default;
2150 protected:
2151 void DoExecute(Args &command, CommandReturnObject &result) override {
2152 Target *target = &GetSelectedTarget();
2153 uint32_t num_dumped = 0;
2155 uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
2156 result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2157 result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2159 if (command.GetArgumentCount() == 0) {
2160 // Dump all sections for all modules images
2161 const size_t num_modules = target->GetImages().GetSize();
2162 if (num_modules == 0) {
2163 result.AppendError("the target has no associated executable images");
2164 return;
2167 result.GetOutputStream().Format("Dumping sections for {0} modules.\n",
2168 num_modules);
2169 for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
2170 if (INTERRUPT_REQUESTED(GetDebugger(),
2171 "Interrupted in dump all sections with {0} of {1} dumped",
2172 image_idx, num_modules))
2173 break;
2175 num_dumped++;
2176 DumpModuleSections(
2177 m_interpreter, result.GetOutputStream(),
2178 target->GetImages().GetModulePointerAtIndex(image_idx));
2180 } else {
2181 // Dump specified images (by basename or fullpath)
2182 const char *arg_cstr;
2183 for (int arg_idx = 0;
2184 (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
2185 ++arg_idx) {
2186 ModuleList module_list;
2187 const size_t num_matches =
2188 FindModulesByName(target, arg_cstr, module_list, true);
2189 if (num_matches > 0) {
2190 for (size_t i = 0; i < num_matches; ++i) {
2191 if (INTERRUPT_REQUESTED(GetDebugger(),
2192 "Interrupted in dump section list with {0} of {1} dumped.",
2193 i, num_matches))
2194 break;
2196 Module *module = module_list.GetModulePointerAtIndex(i);
2197 if (module) {
2198 num_dumped++;
2199 DumpModuleSections(m_interpreter, result.GetOutputStream(),
2200 module);
2203 } else {
2204 // Check the global list
2205 std::lock_guard<std::recursive_mutex> guard(
2206 Module::GetAllocationModuleCollectionMutex());
2208 result.AppendWarningWithFormat(
2209 "Unable to find an image that matches '%s'.\n", arg_cstr);
2214 if (num_dumped > 0)
2215 result.SetStatus(eReturnStatusSuccessFinishResult);
2216 else {
2217 result.AppendError("no matching executable images found");
2222 class CommandObjectTargetModulesDumpClangPCMInfo : public CommandObjectParsed {
2223 public:
2224 CommandObjectTargetModulesDumpClangPCMInfo(CommandInterpreter &interpreter)
2225 : CommandObjectParsed(
2226 interpreter, "target modules dump pcm-info",
2227 "Dump information about the given clang module (pcm).") {
2228 // Take a single file argument.
2229 CommandArgumentData arg{eArgTypeFilename, eArgRepeatPlain};
2230 m_arguments.push_back({arg});
2233 ~CommandObjectTargetModulesDumpClangPCMInfo() override = default;
2235 protected:
2236 void DoExecute(Args &command, CommandReturnObject &result) override {
2237 if (command.GetArgumentCount() != 1) {
2238 result.AppendErrorWithFormat("'%s' takes exactly one pcm path argument.",
2239 m_cmd_name.c_str());
2240 return;
2243 const char *pcm_path = command.GetArgumentAtIndex(0);
2244 const FileSpec pcm_file{pcm_path};
2246 if (pcm_file.GetFileNameExtension() != ".pcm") {
2247 result.AppendError("file must have a .pcm extension");
2248 return;
2251 if (!FileSystem::Instance().Exists(pcm_file)) {
2252 result.AppendError("pcm file does not exist");
2253 return;
2256 clang::CompilerInstance compiler;
2257 compiler.createDiagnostics();
2259 const char *clang_args[] = {"clang", pcm_path};
2260 compiler.setInvocation(clang::createInvocation(clang_args));
2262 // Pass empty deleter to not attempt to free memory that was allocated
2263 // outside of the current scope, possibly statically.
2264 std::shared_ptr<llvm::raw_ostream> Out(
2265 &result.GetOutputStream().AsRawOstream(), [](llvm::raw_ostream *) {});
2266 clang::DumpModuleInfoAction dump_module_info(Out);
2267 // DumpModuleInfoAction requires ObjectFilePCHContainerReader.
2268 compiler.getPCHContainerOperations()->registerReader(
2269 std::make_unique<clang::ObjectFilePCHContainerReader>());
2271 if (compiler.ExecuteAction(dump_module_info))
2272 result.SetStatus(eReturnStatusSuccessFinishResult);
2276 #pragma mark CommandObjectTargetModulesDumpClangAST
2278 // Clang AST dumping command
2280 class CommandObjectTargetModulesDumpClangAST
2281 : public CommandObjectTargetModulesModuleAutoComplete {
2282 public:
2283 CommandObjectTargetModulesDumpClangAST(CommandInterpreter &interpreter)
2284 : CommandObjectTargetModulesModuleAutoComplete(
2285 interpreter, "target modules dump ast",
2286 "Dump the clang ast for a given module's symbol file.",
2287 //"target modules dump ast [<file1> ...]")
2288 nullptr, eCommandRequiresTarget) {}
2290 ~CommandObjectTargetModulesDumpClangAST() override = default;
2292 protected:
2293 void DoExecute(Args &command, CommandReturnObject &result) override {
2294 Target *target = &GetSelectedTarget();
2296 const ModuleList &module_list = target->GetImages();
2297 const size_t num_modules = module_list.GetSize();
2298 if (num_modules == 0) {
2299 result.AppendError("the target has no associated executable images");
2300 return;
2303 if (command.GetArgumentCount() == 0) {
2304 // Dump all ASTs for all modules images
2305 result.GetOutputStream().Format("Dumping clang ast for {0} modules.\n",
2306 num_modules);
2307 for (ModuleSP module_sp : module_list.ModulesNoLocking()) {
2308 if (INTERRUPT_REQUESTED(GetDebugger(), "Interrupted dumping clang ast"))
2309 break;
2310 if (SymbolFile *sf = module_sp->GetSymbolFile())
2311 sf->DumpClangAST(result.GetOutputStream());
2313 result.SetStatus(eReturnStatusSuccessFinishResult);
2314 return;
2317 // Dump specified ASTs (by basename or fullpath)
2318 for (const Args::ArgEntry &arg : command.entries()) {
2319 ModuleList module_list;
2320 const size_t num_matches =
2321 FindModulesByName(target, arg.c_str(), module_list, true);
2322 if (num_matches == 0) {
2323 // Check the global list
2324 std::lock_guard<std::recursive_mutex> guard(
2325 Module::GetAllocationModuleCollectionMutex());
2327 result.AppendWarningWithFormat(
2328 "Unable to find an image that matches '%s'.\n", arg.c_str());
2329 continue;
2332 for (size_t i = 0; i < num_matches; ++i) {
2333 if (INTERRUPT_REQUESTED(GetDebugger(),
2334 "Interrupted in dump clang ast list with {0} of {1} dumped.",
2335 i, num_matches))
2336 break;
2338 Module *m = module_list.GetModulePointerAtIndex(i);
2339 if (SymbolFile *sf = m->GetSymbolFile())
2340 sf->DumpClangAST(result.GetOutputStream());
2343 result.SetStatus(eReturnStatusSuccessFinishResult);
2347 #pragma mark CommandObjectTargetModulesDumpSymfile
2349 // Image debug symbol dumping command
2351 class CommandObjectTargetModulesDumpSymfile
2352 : public CommandObjectTargetModulesModuleAutoComplete {
2353 public:
2354 CommandObjectTargetModulesDumpSymfile(CommandInterpreter &interpreter)
2355 : CommandObjectTargetModulesModuleAutoComplete(
2356 interpreter, "target modules dump symfile",
2357 "Dump the debug symbol file for one or more target modules.",
2358 //"target modules dump symfile [<file1> ...]")
2359 nullptr, eCommandRequiresTarget) {}
2361 ~CommandObjectTargetModulesDumpSymfile() override = default;
2363 protected:
2364 void DoExecute(Args &command, CommandReturnObject &result) override {
2365 Target *target = &GetSelectedTarget();
2366 uint32_t num_dumped = 0;
2368 uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
2369 result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2370 result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2372 if (command.GetArgumentCount() == 0) {
2373 // Dump all sections for all modules images
2374 const ModuleList &target_modules = target->GetImages();
2375 std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
2376 const size_t num_modules = target_modules.GetSize();
2377 if (num_modules == 0) {
2378 result.AppendError("the target has no associated executable images");
2379 return;
2381 result.GetOutputStream().Format(
2382 "Dumping debug symbols for {0} modules.\n", num_modules);
2383 for (ModuleSP module_sp : target_modules.ModulesNoLocking()) {
2384 if (INTERRUPT_REQUESTED(GetDebugger(), "Interrupted in dumping all "
2385 "debug symbols with {0} of {1} modules dumped",
2386 num_dumped, num_modules))
2387 break;
2389 if (DumpModuleSymbolFile(result.GetOutputStream(), module_sp.get()))
2390 num_dumped++;
2392 } else {
2393 // Dump specified images (by basename or fullpath)
2394 const char *arg_cstr;
2395 for (int arg_idx = 0;
2396 (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
2397 ++arg_idx) {
2398 ModuleList module_list;
2399 const size_t num_matches =
2400 FindModulesByName(target, arg_cstr, module_list, true);
2401 if (num_matches > 0) {
2402 for (size_t i = 0; i < num_matches; ++i) {
2403 if (INTERRUPT_REQUESTED(GetDebugger(), "Interrupted dumping {0} "
2404 "of {1} requested modules",
2405 i, num_matches))
2406 break;
2407 Module *module = module_list.GetModulePointerAtIndex(i);
2408 if (module) {
2409 if (DumpModuleSymbolFile(result.GetOutputStream(), module))
2410 num_dumped++;
2413 } else
2414 result.AppendWarningWithFormat(
2415 "Unable to find an image that matches '%s'.\n", arg_cstr);
2419 if (num_dumped > 0)
2420 result.SetStatus(eReturnStatusSuccessFinishResult);
2421 else {
2422 result.AppendError("no matching executable images found");
2427 #pragma mark CommandObjectTargetModulesDumpLineTable
2428 #define LLDB_OPTIONS_target_modules_dump
2429 #include "CommandOptions.inc"
2431 // Image debug line table dumping command
2433 class CommandObjectTargetModulesDumpLineTable
2434 : public CommandObjectTargetModulesSourceFileAutoComplete {
2435 public:
2436 CommandObjectTargetModulesDumpLineTable(CommandInterpreter &interpreter)
2437 : CommandObjectTargetModulesSourceFileAutoComplete(
2438 interpreter, "target modules dump line-table",
2439 "Dump the line table for one or more compilation units.", nullptr,
2440 eCommandRequiresTarget) {}
2442 ~CommandObjectTargetModulesDumpLineTable() override = default;
2444 Options *GetOptions() override { return &m_options; }
2446 protected:
2447 void DoExecute(Args &command, CommandReturnObject &result) override {
2448 Target *target = m_exe_ctx.GetTargetPtr();
2449 uint32_t total_num_dumped = 0;
2451 uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
2452 result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2453 result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2455 if (command.GetArgumentCount() == 0) {
2456 result.AppendError("file option must be specified.");
2457 return;
2458 } else {
2459 // Dump specified images (by basename or fullpath)
2460 const char *arg_cstr;
2461 for (int arg_idx = 0;
2462 (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
2463 ++arg_idx) {
2464 FileSpec file_spec(arg_cstr);
2466 const ModuleList &target_modules = target->GetImages();
2467 std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
2468 size_t num_modules = target_modules.GetSize();
2469 if (num_modules > 0) {
2470 uint32_t num_dumped = 0;
2471 for (ModuleSP module_sp : target_modules.ModulesNoLocking()) {
2472 if (INTERRUPT_REQUESTED(GetDebugger(),
2473 "Interrupted in dump all line tables with "
2474 "{0} of {1} dumped", num_dumped,
2475 num_modules))
2476 break;
2478 if (DumpCompileUnitLineTable(
2479 m_interpreter, result.GetOutputStream(), module_sp.get(),
2480 file_spec,
2481 m_options.m_verbose ? eDescriptionLevelFull
2482 : eDescriptionLevelBrief))
2483 num_dumped++;
2485 if (num_dumped == 0)
2486 result.AppendWarningWithFormat(
2487 "No source filenames matched '%s'.\n", arg_cstr);
2488 else
2489 total_num_dumped += num_dumped;
2494 if (total_num_dumped > 0)
2495 result.SetStatus(eReturnStatusSuccessFinishResult);
2496 else {
2497 result.AppendError("no source filenames matched any command arguments");
2501 class CommandOptions : public Options {
2502 public:
2503 CommandOptions() { OptionParsingStarting(nullptr); }
2505 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2506 ExecutionContext *execution_context) override {
2507 assert(option_idx == 0 && "We only have one option.");
2508 m_verbose = true;
2510 return Status();
2513 void OptionParsingStarting(ExecutionContext *execution_context) override {
2514 m_verbose = false;
2517 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2518 return llvm::ArrayRef(g_target_modules_dump_options);
2521 bool m_verbose;
2524 CommandOptions m_options;
2527 #pragma mark CommandObjectTargetModulesDumpSeparateDebugInfoFiles
2528 #define LLDB_OPTIONS_target_modules_dump_separate_debug_info
2529 #include "CommandOptions.inc"
2531 // Image debug separate debug info dumping command
2533 class CommandObjectTargetModulesDumpSeparateDebugInfoFiles
2534 : public CommandObjectTargetModulesModuleAutoComplete {
2535 public:
2536 CommandObjectTargetModulesDumpSeparateDebugInfoFiles(
2537 CommandInterpreter &interpreter)
2538 : CommandObjectTargetModulesModuleAutoComplete(
2539 interpreter, "target modules dump separate-debug-info",
2540 "List the separate debug info symbol files for one or more target "
2541 "modules.",
2542 nullptr, eCommandRequiresTarget) {}
2544 ~CommandObjectTargetModulesDumpSeparateDebugInfoFiles() override = default;
2546 Options *GetOptions() override { return &m_options; }
2548 class CommandOptions : public Options {
2549 public:
2550 CommandOptions() = default;
2552 ~CommandOptions() override = default;
2554 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2555 ExecutionContext *execution_context) override {
2556 Status error;
2557 const int short_option = m_getopt_table[option_idx].val;
2559 switch (short_option) {
2560 case 'j':
2561 m_json.SetCurrentValue(true);
2562 m_json.SetOptionWasSet();
2563 break;
2565 default:
2566 llvm_unreachable("Unimplemented option");
2568 return error;
2571 void OptionParsingStarting(ExecutionContext *execution_context) override {
2572 m_json.Clear();
2575 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2576 return llvm::ArrayRef(g_target_modules_dump_separate_debug_info_options);
2579 OptionValueBoolean m_json = false;
2582 protected:
2583 void DoExecute(Args &command, CommandReturnObject &result) override {
2584 Target &target = GetSelectedTarget();
2585 uint32_t num_dumped = 0;
2587 uint32_t addr_byte_size = target.GetArchitecture().GetAddressByteSize();
2588 result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2589 result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2591 StructuredData::Array separate_debug_info_lists_by_module;
2592 if (command.GetArgumentCount() == 0) {
2593 // Dump all sections for all modules images
2594 const ModuleList &target_modules = target.GetImages();
2595 std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
2596 const size_t num_modules = target_modules.GetSize();
2597 if (num_modules == 0) {
2598 result.AppendError("the target has no associated executable images");
2599 return;
2601 for (ModuleSP module_sp : target_modules.ModulesNoLocking()) {
2602 if (INTERRUPT_REQUESTED(
2603 GetDebugger(),
2604 "Interrupted in dumping all "
2605 "separate debug info with {0} of {1} modules dumped",
2606 num_dumped, num_modules))
2607 break;
2609 if (GetSeparateDebugInfoList(separate_debug_info_lists_by_module,
2610 module_sp.get()))
2611 num_dumped++;
2613 } else {
2614 // Dump specified images (by basename or fullpath)
2615 const char *arg_cstr;
2616 for (int arg_idx = 0;
2617 (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
2618 ++arg_idx) {
2619 ModuleList module_list;
2620 const size_t num_matches =
2621 FindModulesByName(&target, arg_cstr, module_list, true);
2622 if (num_matches > 0) {
2623 for (size_t i = 0; i < num_matches; ++i) {
2624 if (INTERRUPT_REQUESTED(GetDebugger(),
2625 "Interrupted dumping {0} "
2626 "of {1} requested modules",
2627 i, num_matches))
2628 break;
2629 Module *module = module_list.GetModulePointerAtIndex(i);
2630 if (GetSeparateDebugInfoList(separate_debug_info_lists_by_module,
2631 module))
2632 num_dumped++;
2634 } else
2635 result.AppendWarningWithFormat(
2636 "Unable to find an image that matches '%s'.\n", arg_cstr);
2640 if (num_dumped > 0) {
2641 Stream &strm = result.GetOutputStream();
2642 if (m_options.m_json) {
2643 separate_debug_info_lists_by_module.Dump(strm,
2644 /*pretty_print=*/true);
2645 } else {
2646 // List the debug info files in human readable form.
2647 separate_debug_info_lists_by_module.ForEach(
2648 [&result, &strm](StructuredData::Object *obj) {
2649 if (!obj) {
2650 return false;
2653 // Each item in `separate_debug_info_lists_by_module` should be a
2654 // valid structured data dictionary.
2655 StructuredData::Dictionary *separate_debug_info_list =
2656 obj->GetAsDictionary();
2657 if (!separate_debug_info_list) {
2658 return false;
2661 llvm::StringRef type;
2662 llvm::StringRef symfile;
2663 StructuredData::Array *files;
2664 if (!(separate_debug_info_list->GetValueForKeyAsString("type",
2665 type) &&
2666 separate_debug_info_list->GetValueForKeyAsString("symfile",
2667 symfile) &&
2668 separate_debug_info_list->GetValueForKeyAsArray(
2669 "separate-debug-info-files", files))) {
2670 assert(false);
2673 strm << "Symbol file: " << symfile;
2674 strm.EOL();
2675 strm << "Type: \"" << type << "\"";
2676 strm.EOL();
2677 if (type == "dwo") {
2678 DumpDwoFilesTable(strm, *files);
2679 } else if (type == "oso") {
2680 DumpOsoFilesTable(strm, *files);
2681 } else {
2682 result.AppendWarningWithFormat(
2683 "Found unsupported debug info type '%s'.\n",
2684 type.str().c_str());
2686 return true;
2689 result.SetStatus(eReturnStatusSuccessFinishResult);
2690 } else {
2691 result.AppendError("no matching executable images found");
2695 CommandOptions m_options;
2698 #pragma mark CommandObjectTargetModulesDump
2700 // Dump multi-word command for target modules
2702 class CommandObjectTargetModulesDump : public CommandObjectMultiword {
2703 public:
2704 // Constructors and Destructors
2705 CommandObjectTargetModulesDump(CommandInterpreter &interpreter)
2706 : CommandObjectMultiword(
2707 interpreter, "target modules dump",
2708 "Commands for dumping information about one or more target "
2709 "modules.",
2710 "target modules dump "
2711 "[objfile|symtab|sections|ast|symfile|line-table|pcm-info|separate-"
2712 "debug-info] "
2713 "[<file1> <file2> ...]") {
2714 LoadSubCommand("objfile",
2715 CommandObjectSP(
2716 new CommandObjectTargetModulesDumpObjfile(interpreter)));
2717 LoadSubCommand(
2718 "symtab",
2719 CommandObjectSP(new CommandObjectTargetModulesDumpSymtab(interpreter)));
2720 LoadSubCommand("sections",
2721 CommandObjectSP(new CommandObjectTargetModulesDumpSections(
2722 interpreter)));
2723 LoadSubCommand("symfile",
2724 CommandObjectSP(
2725 new CommandObjectTargetModulesDumpSymfile(interpreter)));
2726 LoadSubCommand(
2727 "ast", CommandObjectSP(
2728 new CommandObjectTargetModulesDumpClangAST(interpreter)));
2729 LoadSubCommand("line-table",
2730 CommandObjectSP(new CommandObjectTargetModulesDumpLineTable(
2731 interpreter)));
2732 LoadSubCommand(
2733 "pcm-info",
2734 CommandObjectSP(
2735 new CommandObjectTargetModulesDumpClangPCMInfo(interpreter)));
2736 LoadSubCommand("separate-debug-info",
2737 CommandObjectSP(
2738 new CommandObjectTargetModulesDumpSeparateDebugInfoFiles(
2739 interpreter)));
2742 ~CommandObjectTargetModulesDump() override = default;
2745 class CommandObjectTargetModulesAdd : public CommandObjectParsed {
2746 public:
2747 CommandObjectTargetModulesAdd(CommandInterpreter &interpreter)
2748 : CommandObjectParsed(interpreter, "target modules add",
2749 "Add a new module to the current target's modules.",
2750 "target modules add [<module>]",
2751 eCommandRequiresTarget),
2752 m_symbol_file(LLDB_OPT_SET_1, false, "symfile", 's', 0,
2753 eArgTypeFilename,
2754 "Fullpath to a stand alone debug "
2755 "symbols file for when debug symbols "
2756 "are not in the executable.") {
2757 m_option_group.Append(&m_uuid_option_group, LLDB_OPT_SET_ALL,
2758 LLDB_OPT_SET_1);
2759 m_option_group.Append(&m_symbol_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2760 m_option_group.Finalize();
2761 CommandArgumentData module_arg{eArgTypePath, eArgRepeatStar};
2762 m_arguments.push_back({module_arg});
2765 ~CommandObjectTargetModulesAdd() override = default;
2767 Options *GetOptions() override { return &m_option_group; }
2769 void
2770 HandleArgumentCompletion(CompletionRequest &request,
2771 OptionElementVector &opt_element_vector) override {
2772 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
2773 GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr);
2776 protected:
2777 OptionGroupOptions m_option_group;
2778 OptionGroupUUID m_uuid_option_group;
2779 OptionGroupFile m_symbol_file;
2781 void DoExecute(Args &args, CommandReturnObject &result) override {
2782 Target *target = &GetSelectedTarget();
2783 bool flush = false;
2785 const size_t argc = args.GetArgumentCount();
2786 if (argc == 0) {
2787 if (m_uuid_option_group.GetOptionValue().OptionWasSet()) {
2788 // We are given a UUID only, go locate the file
2789 ModuleSpec module_spec;
2790 module_spec.GetUUID() =
2791 m_uuid_option_group.GetOptionValue().GetCurrentValue();
2792 if (m_symbol_file.GetOptionValue().OptionWasSet())
2793 module_spec.GetSymbolFileSpec() =
2794 m_symbol_file.GetOptionValue().GetCurrentValue();
2795 Status error;
2796 if (Symbols::DownloadObjectAndSymbolFile(module_spec, error)) {
2797 ModuleSP module_sp(
2798 target->GetOrCreateModule(module_spec, true /* notify */));
2799 if (module_sp) {
2800 result.SetStatus(eReturnStatusSuccessFinishResult);
2801 return;
2802 } else {
2803 StreamString strm;
2804 module_spec.GetUUID().Dump(strm);
2805 if (module_spec.GetFileSpec()) {
2806 if (module_spec.GetSymbolFileSpec()) {
2807 result.AppendErrorWithFormat(
2808 "Unable to create the executable or symbol file with "
2809 "UUID %s with path %s and symbol file %s",
2810 strm.GetData(), module_spec.GetFileSpec().GetPath().c_str(),
2811 module_spec.GetSymbolFileSpec().GetPath().c_str());
2812 } else {
2813 result.AppendErrorWithFormat(
2814 "Unable to create the executable or symbol file with "
2815 "UUID %s with path %s",
2816 strm.GetData(),
2817 module_spec.GetFileSpec().GetPath().c_str());
2819 } else {
2820 result.AppendErrorWithFormat("Unable to create the executable "
2821 "or symbol file with UUID %s",
2822 strm.GetData());
2824 return;
2826 } else {
2827 StreamString strm;
2828 module_spec.GetUUID().Dump(strm);
2829 result.AppendErrorWithFormat(
2830 "Unable to locate the executable or symbol file with UUID %s",
2831 strm.GetData());
2832 result.SetError(error);
2833 return;
2835 } else {
2836 result.AppendError(
2837 "one or more executable image paths must be specified");
2838 return;
2840 } else {
2841 for (auto &entry : args.entries()) {
2842 if (entry.ref().empty())
2843 continue;
2845 FileSpec file_spec(entry.ref());
2846 if (FileSystem::Instance().Exists(file_spec)) {
2847 ModuleSpec module_spec(file_spec);
2848 if (m_uuid_option_group.GetOptionValue().OptionWasSet())
2849 module_spec.GetUUID() =
2850 m_uuid_option_group.GetOptionValue().GetCurrentValue();
2851 if (m_symbol_file.GetOptionValue().OptionWasSet())
2852 module_spec.GetSymbolFileSpec() =
2853 m_symbol_file.GetOptionValue().GetCurrentValue();
2854 if (!module_spec.GetArchitecture().IsValid())
2855 module_spec.GetArchitecture() = target->GetArchitecture();
2856 Status error;
2857 ModuleSP module_sp(target->GetOrCreateModule(
2858 module_spec, true /* notify */, &error));
2859 if (!module_sp) {
2860 const char *error_cstr = error.AsCString();
2861 if (error_cstr)
2862 result.AppendError(error_cstr);
2863 else
2864 result.AppendErrorWithFormat("unsupported module: %s",
2865 entry.c_str());
2866 return;
2867 } else {
2868 flush = true;
2870 result.SetStatus(eReturnStatusSuccessFinishResult);
2871 } else {
2872 std::string resolved_path = file_spec.GetPath();
2873 if (resolved_path != entry.ref()) {
2874 result.AppendErrorWithFormat(
2875 "invalid module path '%s' with resolved path '%s'\n",
2876 entry.ref().str().c_str(), resolved_path.c_str());
2877 break;
2879 result.AppendErrorWithFormat("invalid module path '%s'\n",
2880 entry.c_str());
2881 break;
2886 if (flush) {
2887 ProcessSP process = target->GetProcessSP();
2888 if (process)
2889 process->Flush();
2894 class CommandObjectTargetModulesLoad
2895 : public CommandObjectTargetModulesModuleAutoComplete {
2896 public:
2897 CommandObjectTargetModulesLoad(CommandInterpreter &interpreter)
2898 : CommandObjectTargetModulesModuleAutoComplete(
2899 interpreter, "target modules load",
2900 "Set the load addresses for one or more sections in a target "
2901 "module.",
2902 "target modules load [--file <module> --uuid <uuid>] <sect-name> "
2903 "<address> [<sect-name> <address> ....]",
2904 eCommandRequiresTarget),
2905 m_file_option(LLDB_OPT_SET_1, false, "file", 'f', 0, eArgTypeName,
2906 "Fullpath or basename for module to load.", ""),
2907 m_load_option(LLDB_OPT_SET_1, false, "load", 'l',
2908 "Write file contents to the memory.", false, true),
2909 m_pc_option(LLDB_OPT_SET_1, false, "set-pc-to-entry", 'p',
2910 "Set PC to the entry point."
2911 " Only applicable with '--load' option.",
2912 false, true),
2913 m_slide_option(LLDB_OPT_SET_1, false, "slide", 's', 0, eArgTypeOffset,
2914 "Set the load address for all sections to be the "
2915 "virtual address in the file plus the offset.",
2916 0) {
2917 m_option_group.Append(&m_uuid_option_group, LLDB_OPT_SET_ALL,
2918 LLDB_OPT_SET_1);
2919 m_option_group.Append(&m_file_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2920 m_option_group.Append(&m_load_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2921 m_option_group.Append(&m_pc_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2922 m_option_group.Append(&m_slide_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2923 m_option_group.Finalize();
2926 ~CommandObjectTargetModulesLoad() override = default;
2928 Options *GetOptions() override { return &m_option_group; }
2930 protected:
2931 void DoExecute(Args &args, CommandReturnObject &result) override {
2932 Target *target = &GetSelectedTarget();
2933 const bool load = m_load_option.GetOptionValue().GetCurrentValue();
2934 const bool set_pc = m_pc_option.GetOptionValue().GetCurrentValue();
2936 const size_t argc = args.GetArgumentCount();
2937 ModuleSpec module_spec;
2938 bool search_using_module_spec = false;
2940 // Allow "load" option to work without --file or --uuid option.
2941 if (load) {
2942 if (!m_file_option.GetOptionValue().OptionWasSet() &&
2943 !m_uuid_option_group.GetOptionValue().OptionWasSet()) {
2944 ModuleList &module_list = target->GetImages();
2945 if (module_list.GetSize() == 1) {
2946 search_using_module_spec = true;
2947 module_spec.GetFileSpec() =
2948 module_list.GetModuleAtIndex(0)->GetFileSpec();
2953 if (m_file_option.GetOptionValue().OptionWasSet()) {
2954 search_using_module_spec = true;
2955 const char *arg_cstr = m_file_option.GetOptionValue().GetCurrentValue();
2956 const bool use_global_module_list = true;
2957 ModuleList module_list;
2958 const size_t num_matches = FindModulesByName(
2959 target, arg_cstr, module_list, use_global_module_list);
2960 if (num_matches == 1) {
2961 module_spec.GetFileSpec() =
2962 module_list.GetModuleAtIndex(0)->GetFileSpec();
2963 } else if (num_matches > 1) {
2964 search_using_module_spec = false;
2965 result.AppendErrorWithFormat(
2966 "more than 1 module matched by name '%s'\n", arg_cstr);
2967 } else {
2968 search_using_module_spec = false;
2969 result.AppendErrorWithFormat("no object file for module '%s'\n",
2970 arg_cstr);
2974 if (m_uuid_option_group.GetOptionValue().OptionWasSet()) {
2975 search_using_module_spec = true;
2976 module_spec.GetUUID() =
2977 m_uuid_option_group.GetOptionValue().GetCurrentValue();
2980 if (search_using_module_spec) {
2981 ModuleList matching_modules;
2982 target->GetImages().FindModules(module_spec, matching_modules);
2983 const size_t num_matches = matching_modules.GetSize();
2985 char path[PATH_MAX];
2986 if (num_matches == 1) {
2987 Module *module = matching_modules.GetModulePointerAtIndex(0);
2988 if (module) {
2989 ObjectFile *objfile = module->GetObjectFile();
2990 if (objfile) {
2991 SectionList *section_list = module->GetSectionList();
2992 if (section_list) {
2993 bool changed = false;
2994 if (argc == 0) {
2995 if (m_slide_option.GetOptionValue().OptionWasSet()) {
2996 const addr_t slide =
2997 m_slide_option.GetOptionValue().GetCurrentValue();
2998 const bool slide_is_offset = true;
2999 module->SetLoadAddress(*target, slide, slide_is_offset,
3000 changed);
3001 } else {
3002 result.AppendError("one or more section name + load "
3003 "address pair must be specified");
3004 return;
3006 } else {
3007 if (m_slide_option.GetOptionValue().OptionWasSet()) {
3008 result.AppendError("The \"--slide <offset>\" option can't "
3009 "be used in conjunction with setting "
3010 "section load addresses.\n");
3011 return;
3014 for (size_t i = 0; i < argc; i += 2) {
3015 const char *sect_name = args.GetArgumentAtIndex(i);
3016 const char *load_addr_cstr = args.GetArgumentAtIndex(i + 1);
3017 if (sect_name && load_addr_cstr) {
3018 ConstString const_sect_name(sect_name);
3019 addr_t load_addr;
3020 if (llvm::to_integer(load_addr_cstr, load_addr)) {
3021 SectionSP section_sp(
3022 section_list->FindSectionByName(const_sect_name));
3023 if (section_sp) {
3024 if (section_sp->IsThreadSpecific()) {
3025 result.AppendErrorWithFormat(
3026 "thread specific sections are not yet "
3027 "supported (section '%s')\n",
3028 sect_name);
3029 break;
3030 } else {
3031 if (target->GetSectionLoadList()
3032 .SetSectionLoadAddress(section_sp, load_addr))
3033 changed = true;
3034 result.AppendMessageWithFormat(
3035 "section '%s' loaded at 0x%" PRIx64 "\n",
3036 sect_name, load_addr);
3038 } else {
3039 result.AppendErrorWithFormat("no section found that "
3040 "matches the section "
3041 "name '%s'\n",
3042 sect_name);
3043 break;
3045 } else {
3046 result.AppendErrorWithFormat(
3047 "invalid load address string '%s'\n", load_addr_cstr);
3048 break;
3050 } else {
3051 if (sect_name)
3052 result.AppendError("section names must be followed by "
3053 "a load address.\n");
3054 else
3055 result.AppendError("one or more section name + load "
3056 "address pair must be specified.\n");
3057 break;
3062 if (changed) {
3063 target->ModulesDidLoad(matching_modules);
3064 Process *process = m_exe_ctx.GetProcessPtr();
3065 if (process)
3066 process->Flush();
3068 if (load) {
3069 ProcessSP process = target->CalculateProcess();
3070 Address file_entry = objfile->GetEntryPointAddress();
3071 if (!process) {
3072 result.AppendError("No process");
3073 return;
3075 if (set_pc && !file_entry.IsValid()) {
3076 result.AppendError("No entry address in object file");
3077 return;
3079 std::vector<ObjectFile::LoadableData> loadables(
3080 objfile->GetLoadableData(*target));
3081 if (loadables.size() == 0) {
3082 result.AppendError("No loadable sections");
3083 return;
3085 Status error = process->WriteObjectFile(std::move(loadables));
3086 if (error.Fail()) {
3087 result.AppendError(error.AsCString());
3088 return;
3090 if (set_pc) {
3091 ThreadList &thread_list = process->GetThreadList();
3092 RegisterContextSP reg_context(
3093 thread_list.GetSelectedThread()->GetRegisterContext());
3094 addr_t file_entry_addr = file_entry.GetLoadAddress(target);
3095 if (!reg_context->SetPC(file_entry_addr)) {
3096 result.AppendErrorWithFormat("failed to set PC value to "
3097 "0x%" PRIx64 "\n",
3098 file_entry_addr);
3102 } else {
3103 module->GetFileSpec().GetPath(path, sizeof(path));
3104 result.AppendErrorWithFormat("no sections in object file '%s'\n",
3105 path);
3107 } else {
3108 module->GetFileSpec().GetPath(path, sizeof(path));
3109 result.AppendErrorWithFormat("no object file for module '%s'\n",
3110 path);
3112 } else {
3113 FileSpec *module_spec_file = module_spec.GetFileSpecPtr();
3114 if (module_spec_file) {
3115 module_spec_file->GetPath(path, sizeof(path));
3116 result.AppendErrorWithFormat("invalid module '%s'.\n", path);
3117 } else
3118 result.AppendError("no module spec");
3120 } else {
3121 std::string uuid_str;
3123 if (module_spec.GetFileSpec())
3124 module_spec.GetFileSpec().GetPath(path, sizeof(path));
3125 else
3126 path[0] = '\0';
3128 if (module_spec.GetUUIDPtr())
3129 uuid_str = module_spec.GetUUID().GetAsString();
3130 if (num_matches > 1) {
3131 result.AppendErrorWithFormat(
3132 "multiple modules match%s%s%s%s:\n", path[0] ? " file=" : "",
3133 path, !uuid_str.empty() ? " uuid=" : "", uuid_str.c_str());
3134 for (size_t i = 0; i < num_matches; ++i) {
3135 if (matching_modules.GetModulePointerAtIndex(i)
3136 ->GetFileSpec()
3137 .GetPath(path, sizeof(path)))
3138 result.AppendMessageWithFormat("%s\n", path);
3140 } else {
3141 result.AppendErrorWithFormat(
3142 "no modules were found that match%s%s%s%s.\n",
3143 path[0] ? " file=" : "", path, !uuid_str.empty() ? " uuid=" : "",
3144 uuid_str.c_str());
3147 } else {
3148 result.AppendError("either the \"--file <module>\" or the \"--uuid "
3149 "<uuid>\" option must be specified.\n");
3153 OptionGroupOptions m_option_group;
3154 OptionGroupUUID m_uuid_option_group;
3155 OptionGroupString m_file_option;
3156 OptionGroupBoolean m_load_option;
3157 OptionGroupBoolean m_pc_option;
3158 OptionGroupUInt64 m_slide_option;
3161 #pragma mark CommandObjectTargetModulesList
3162 // List images with associated information
3163 #define LLDB_OPTIONS_target_modules_list
3164 #include "CommandOptions.inc"
3166 class CommandObjectTargetModulesList : public CommandObjectParsed {
3167 public:
3168 class CommandOptions : public Options {
3169 public:
3170 CommandOptions() = default;
3172 ~CommandOptions() override = default;
3174 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
3175 ExecutionContext *execution_context) override {
3176 Status error;
3178 const int short_option = m_getopt_table[option_idx].val;
3179 if (short_option == 'g') {
3180 m_use_global_module_list = true;
3181 } else if (short_option == 'a') {
3182 m_module_addr = OptionArgParser::ToAddress(
3183 execution_context, option_arg, LLDB_INVALID_ADDRESS, &error);
3184 } else {
3185 unsigned long width = 0;
3186 option_arg.getAsInteger(0, width);
3187 m_format_array.push_back(std::make_pair(short_option, width));
3189 return error;
3192 void OptionParsingStarting(ExecutionContext *execution_context) override {
3193 m_format_array.clear();
3194 m_use_global_module_list = false;
3195 m_module_addr = LLDB_INVALID_ADDRESS;
3198 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
3199 return llvm::ArrayRef(g_target_modules_list_options);
3202 // Instance variables to hold the values for command options.
3203 typedef std::vector<std::pair<char, uint32_t>> FormatWidthCollection;
3204 FormatWidthCollection m_format_array;
3205 bool m_use_global_module_list = false;
3206 lldb::addr_t m_module_addr = LLDB_INVALID_ADDRESS;
3209 CommandObjectTargetModulesList(CommandInterpreter &interpreter)
3210 : CommandObjectParsed(
3211 interpreter, "target modules list",
3212 "List current executable and dependent shared library images.") {
3213 CommandArgumentData module_arg{eArgTypeShlibName, eArgRepeatStar};
3214 m_arguments.push_back({module_arg});
3217 ~CommandObjectTargetModulesList() override = default;
3219 Options *GetOptions() override { return &m_options; }
3221 protected:
3222 void DoExecute(Args &command, CommandReturnObject &result) override {
3223 Target *target = GetDebugger().GetSelectedTarget().get();
3224 const bool use_global_module_list = m_options.m_use_global_module_list;
3225 // Define a local module list here to ensure it lives longer than any
3226 // "locker" object which might lock its contents below (through the
3227 // "module_list_ptr" variable).
3228 ModuleList module_list;
3229 if (target == nullptr && !use_global_module_list) {
3230 result.AppendError("invalid target, create a debug target using the "
3231 "'target create' command");
3232 return;
3233 } else {
3234 if (target) {
3235 uint32_t addr_byte_size =
3236 target->GetArchitecture().GetAddressByteSize();
3237 result.GetOutputStream().SetAddressByteSize(addr_byte_size);
3238 result.GetErrorStream().SetAddressByteSize(addr_byte_size);
3240 // Dump all sections for all modules images
3241 Stream &strm = result.GetOutputStream();
3243 if (m_options.m_module_addr != LLDB_INVALID_ADDRESS) {
3244 if (target) {
3245 Address module_address;
3246 if (module_address.SetLoadAddress(m_options.m_module_addr, target)) {
3247 ModuleSP module_sp(module_address.GetModule());
3248 if (module_sp) {
3249 PrintModule(target, module_sp.get(), 0, strm);
3250 result.SetStatus(eReturnStatusSuccessFinishResult);
3251 } else {
3252 result.AppendErrorWithFormat(
3253 "Couldn't find module matching address: 0x%" PRIx64 ".",
3254 m_options.m_module_addr);
3256 } else {
3257 result.AppendErrorWithFormat(
3258 "Couldn't find module containing address: 0x%" PRIx64 ".",
3259 m_options.m_module_addr);
3261 } else {
3262 result.AppendError(
3263 "Can only look up modules by address with a valid target.");
3265 return;
3268 size_t num_modules = 0;
3270 // This locker will be locked on the mutex in module_list_ptr if it is
3271 // non-nullptr. Otherwise it will lock the
3272 // AllocationModuleCollectionMutex when accessing the global module list
3273 // directly.
3274 std::unique_lock<std::recursive_mutex> guard(
3275 Module::GetAllocationModuleCollectionMutex(), std::defer_lock);
3277 const ModuleList *module_list_ptr = nullptr;
3278 const size_t argc = command.GetArgumentCount();
3279 if (argc == 0) {
3280 if (use_global_module_list) {
3281 guard.lock();
3282 num_modules = Module::GetNumberAllocatedModules();
3283 } else {
3284 module_list_ptr = &target->GetImages();
3286 } else {
3287 for (const Args::ArgEntry &arg : command) {
3288 // Dump specified images (by basename or fullpath)
3289 const size_t num_matches = FindModulesByName(
3290 target, arg.c_str(), module_list, use_global_module_list);
3291 if (num_matches == 0) {
3292 if (argc == 1) {
3293 result.AppendErrorWithFormat("no modules found that match '%s'",
3294 arg.c_str());
3295 return;
3300 module_list_ptr = &module_list;
3303 std::unique_lock<std::recursive_mutex> lock;
3304 if (module_list_ptr != nullptr) {
3305 lock =
3306 std::unique_lock<std::recursive_mutex>(module_list_ptr->GetMutex());
3308 num_modules = module_list_ptr->GetSize();
3311 if (num_modules > 0) {
3312 for (uint32_t image_idx = 0; image_idx < num_modules; ++image_idx) {
3313 ModuleSP module_sp;
3314 Module *module;
3315 if (module_list_ptr) {
3316 module_sp = module_list_ptr->GetModuleAtIndexUnlocked(image_idx);
3317 module = module_sp.get();
3318 } else {
3319 module = Module::GetAllocatedModuleAtIndex(image_idx);
3320 module_sp = module->shared_from_this();
3323 const size_t indent = strm.Printf("[%3u] ", image_idx);
3324 PrintModule(target, module, indent, strm);
3326 result.SetStatus(eReturnStatusSuccessFinishResult);
3327 } else {
3328 if (argc) {
3329 if (use_global_module_list)
3330 result.AppendError(
3331 "the global module list has no matching modules");
3332 else
3333 result.AppendError("the target has no matching modules");
3334 } else {
3335 if (use_global_module_list)
3336 result.AppendError("the global module list is empty");
3337 else
3338 result.AppendError(
3339 "the target has no associated executable images");
3341 return;
3346 void PrintModule(Target *target, Module *module, int indent, Stream &strm) {
3347 if (module == nullptr) {
3348 strm.PutCString("Null module");
3349 return;
3352 bool dump_object_name = false;
3353 if (m_options.m_format_array.empty()) {
3354 m_options.m_format_array.push_back(std::make_pair('u', 0));
3355 m_options.m_format_array.push_back(std::make_pair('h', 0));
3356 m_options.m_format_array.push_back(std::make_pair('f', 0));
3357 m_options.m_format_array.push_back(std::make_pair('S', 0));
3359 const size_t num_entries = m_options.m_format_array.size();
3360 bool print_space = false;
3361 for (size_t i = 0; i < num_entries; ++i) {
3362 if (print_space)
3363 strm.PutChar(' ');
3364 print_space = true;
3365 const char format_char = m_options.m_format_array[i].first;
3366 uint32_t width = m_options.m_format_array[i].second;
3367 switch (format_char) {
3368 case 'A':
3369 DumpModuleArchitecture(strm, module, false, width);
3370 break;
3372 case 't':
3373 DumpModuleArchitecture(strm, module, true, width);
3374 break;
3376 case 'f':
3377 DumpFullpath(strm, &module->GetFileSpec(), width);
3378 dump_object_name = true;
3379 break;
3381 case 'd':
3382 DumpDirectory(strm, &module->GetFileSpec(), width);
3383 break;
3385 case 'b':
3386 DumpBasename(strm, &module->GetFileSpec(), width);
3387 dump_object_name = true;
3388 break;
3390 case 'h':
3391 case 'o':
3392 // Image header address
3394 uint32_t addr_nibble_width =
3395 target ? (target->GetArchitecture().GetAddressByteSize() * 2)
3396 : 16;
3398 ObjectFile *objfile = module->GetObjectFile();
3399 if (objfile) {
3400 Address base_addr(objfile->GetBaseAddress());
3401 if (base_addr.IsValid()) {
3402 if (target && !target->GetSectionLoadList().IsEmpty()) {
3403 lldb::addr_t load_addr = base_addr.GetLoadAddress(target);
3404 if (load_addr == LLDB_INVALID_ADDRESS) {
3405 base_addr.Dump(&strm, target,
3406 Address::DumpStyleModuleWithFileAddress,
3407 Address::DumpStyleFileAddress);
3408 } else {
3409 if (format_char == 'o') {
3410 // Show the offset of slide for the image
3411 strm.Printf("0x%*.*" PRIx64, addr_nibble_width,
3412 addr_nibble_width,
3413 load_addr - base_addr.GetFileAddress());
3414 } else {
3415 // Show the load address of the image
3416 strm.Printf("0x%*.*" PRIx64, addr_nibble_width,
3417 addr_nibble_width, load_addr);
3420 break;
3422 // The address was valid, but the image isn't loaded, output the
3423 // address in an appropriate format
3424 base_addr.Dump(&strm, target, Address::DumpStyleFileAddress);
3425 break;
3428 strm.Printf("%*s", addr_nibble_width + 2, "");
3430 break;
3432 case 'r': {
3433 size_t ref_count = 0;
3434 ModuleSP module_sp(module->shared_from_this());
3435 if (module_sp) {
3436 // Take one away to make sure we don't count our local "module_sp"
3437 ref_count = module_sp.use_count() - 1;
3439 if (width)
3440 strm.Printf("{%*" PRIu64 "}", width, (uint64_t)ref_count);
3441 else
3442 strm.Printf("{%" PRIu64 "}", (uint64_t)ref_count);
3443 } break;
3445 case 's':
3446 case 'S': {
3447 if (const SymbolFile *symbol_file = module->GetSymbolFile()) {
3448 const FileSpec symfile_spec =
3449 symbol_file->GetObjectFile()->GetFileSpec();
3450 if (format_char == 'S') {
3451 // Dump symbol file only if different from module file
3452 if (!symfile_spec || symfile_spec == module->GetFileSpec()) {
3453 print_space = false;
3454 break;
3456 // Add a newline and indent past the index
3457 strm.Printf("\n%*s", indent, "");
3459 DumpFullpath(strm, &symfile_spec, width);
3460 dump_object_name = true;
3461 break;
3463 strm.Printf("%.*s", width, "<NONE>");
3464 } break;
3466 case 'm':
3467 strm.Format("{0:%c}", llvm::fmt_align(module->GetModificationTime(),
3468 llvm::AlignStyle::Left, width));
3469 break;
3471 case 'p':
3472 strm.Printf("%p", static_cast<void *>(module));
3473 break;
3475 case 'u':
3476 DumpModuleUUID(strm, module);
3477 break;
3479 default:
3480 break;
3483 if (dump_object_name) {
3484 const char *object_name = module->GetObjectName().GetCString();
3485 if (object_name)
3486 strm.Printf("(%s)", object_name);
3488 strm.EOL();
3491 CommandOptions m_options;
3494 #pragma mark CommandObjectTargetModulesShowUnwind
3496 // Lookup unwind information in images
3497 #define LLDB_OPTIONS_target_modules_show_unwind
3498 #include "CommandOptions.inc"
3500 class CommandObjectTargetModulesShowUnwind : public CommandObjectParsed {
3501 public:
3502 enum {
3503 eLookupTypeInvalid = -1,
3504 eLookupTypeAddress = 0,
3505 eLookupTypeSymbol,
3506 eLookupTypeFunction,
3507 eLookupTypeFunctionOrSymbol,
3508 kNumLookupTypes
3511 class CommandOptions : public Options {
3512 public:
3513 CommandOptions() = default;
3515 ~CommandOptions() override = default;
3517 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
3518 ExecutionContext *execution_context) override {
3519 Status error;
3521 const int short_option = m_getopt_table[option_idx].val;
3523 switch (short_option) {
3524 case 'a': {
3525 m_str = std::string(option_arg);
3526 m_type = eLookupTypeAddress;
3527 m_addr = OptionArgParser::ToAddress(execution_context, option_arg,
3528 LLDB_INVALID_ADDRESS, &error);
3529 if (m_addr == LLDB_INVALID_ADDRESS)
3530 error.SetErrorStringWithFormat("invalid address string '%s'",
3531 option_arg.str().c_str());
3532 break;
3535 case 'n':
3536 m_str = std::string(option_arg);
3537 m_type = eLookupTypeFunctionOrSymbol;
3538 break;
3540 default:
3541 llvm_unreachable("Unimplemented option");
3544 return error;
3547 void OptionParsingStarting(ExecutionContext *execution_context) override {
3548 m_type = eLookupTypeInvalid;
3549 m_str.clear();
3550 m_addr = LLDB_INVALID_ADDRESS;
3553 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
3554 return llvm::ArrayRef(g_target_modules_show_unwind_options);
3557 // Instance variables to hold the values for command options.
3559 int m_type = eLookupTypeInvalid; // Should be a eLookupTypeXXX enum after
3560 // parsing options
3561 std::string m_str; // Holds name lookup
3562 lldb::addr_t m_addr = LLDB_INVALID_ADDRESS; // Holds the address to lookup
3565 CommandObjectTargetModulesShowUnwind(CommandInterpreter &interpreter)
3566 : CommandObjectParsed(
3567 interpreter, "target modules show-unwind",
3568 "Show synthesized unwind instructions for a function.", nullptr,
3569 eCommandRequiresTarget | eCommandRequiresProcess |
3570 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {}
3572 ~CommandObjectTargetModulesShowUnwind() override = default;
3574 Options *GetOptions() override { return &m_options; }
3576 protected:
3577 void DoExecute(Args &command, CommandReturnObject &result) override {
3578 Target *target = m_exe_ctx.GetTargetPtr();
3579 Process *process = m_exe_ctx.GetProcessPtr();
3580 ABI *abi = nullptr;
3581 if (process)
3582 abi = process->GetABI().get();
3584 if (process == nullptr) {
3585 result.AppendError(
3586 "You must have a process running to use this command.");
3587 return;
3590 ThreadList threads(process->GetThreadList());
3591 if (threads.GetSize() == 0) {
3592 result.AppendError("The process must be paused to use this command.");
3593 return;
3596 ThreadSP thread(threads.GetThreadAtIndex(0));
3597 if (!thread) {
3598 result.AppendError("The process must be paused to use this command.");
3599 return;
3602 SymbolContextList sc_list;
3604 if (m_options.m_type == eLookupTypeFunctionOrSymbol) {
3605 ConstString function_name(m_options.m_str.c_str());
3606 ModuleFunctionSearchOptions function_options;
3607 function_options.include_symbols = true;
3608 function_options.include_inlines = false;
3609 target->GetImages().FindFunctions(function_name, eFunctionNameTypeAuto,
3610 function_options, sc_list);
3611 } else if (m_options.m_type == eLookupTypeAddress && target) {
3612 Address addr;
3613 if (target->GetSectionLoadList().ResolveLoadAddress(m_options.m_addr,
3614 addr)) {
3615 SymbolContext sc;
3616 ModuleSP module_sp(addr.GetModule());
3617 module_sp->ResolveSymbolContextForAddress(addr,
3618 eSymbolContextEverything, sc);
3619 if (sc.function || sc.symbol) {
3620 sc_list.Append(sc);
3623 } else {
3624 result.AppendError(
3625 "address-expression or function name option must be specified.");
3626 return;
3629 if (sc_list.GetSize() == 0) {
3630 result.AppendErrorWithFormat("no unwind data found that matches '%s'.",
3631 m_options.m_str.c_str());
3632 return;
3635 for (const SymbolContext &sc : sc_list) {
3636 if (sc.symbol == nullptr && sc.function == nullptr)
3637 continue;
3638 if (!sc.module_sp || sc.module_sp->GetObjectFile() == nullptr)
3639 continue;
3640 AddressRange range;
3641 if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0,
3642 false, range))
3643 continue;
3644 if (!range.GetBaseAddress().IsValid())
3645 continue;
3646 ConstString funcname(sc.GetFunctionName());
3647 if (funcname.IsEmpty())
3648 continue;
3649 addr_t start_addr = range.GetBaseAddress().GetLoadAddress(target);
3650 if (abi)
3651 start_addr = abi->FixCodeAddress(start_addr);
3653 FuncUnwindersSP func_unwinders_sp(
3654 sc.module_sp->GetUnwindTable()
3655 .GetUncachedFuncUnwindersContainingAddress(start_addr, sc));
3656 if (!func_unwinders_sp)
3657 continue;
3659 result.GetOutputStream().Printf(
3660 "UNWIND PLANS for %s`%s (start addr 0x%" PRIx64 ")\n",
3661 sc.module_sp->GetPlatformFileSpec().GetFilename().AsCString(),
3662 funcname.AsCString(), start_addr);
3664 Args args;
3665 target->GetUserSpecifiedTrapHandlerNames(args);
3666 size_t count = args.GetArgumentCount();
3667 for (size_t i = 0; i < count; i++) {
3668 const char *trap_func_name = args.GetArgumentAtIndex(i);
3669 if (strcmp(funcname.GetCString(), trap_func_name) == 0)
3670 result.GetOutputStream().Printf(
3671 "This function is "
3672 "treated as a trap handler function via user setting.\n");
3674 PlatformSP platform_sp(target->GetPlatform());
3675 if (platform_sp) {
3676 const std::vector<ConstString> trap_handler_names(
3677 platform_sp->GetTrapHandlerSymbolNames());
3678 for (ConstString trap_name : trap_handler_names) {
3679 if (trap_name == funcname) {
3680 result.GetOutputStream().Printf(
3681 "This function's "
3682 "name is listed by the platform as a trap handler.\n");
3687 result.GetOutputStream().Printf("\n");
3689 UnwindPlanSP non_callsite_unwind_plan =
3690 func_unwinders_sp->GetUnwindPlanAtNonCallSite(*target, *thread);
3691 if (non_callsite_unwind_plan) {
3692 result.GetOutputStream().Printf(
3693 "Asynchronous (not restricted to call-sites) UnwindPlan is '%s'\n",
3694 non_callsite_unwind_plan->GetSourceName().AsCString());
3696 UnwindPlanSP callsite_unwind_plan =
3697 func_unwinders_sp->GetUnwindPlanAtCallSite(*target, *thread);
3698 if (callsite_unwind_plan) {
3699 result.GetOutputStream().Printf(
3700 "Synchronous (restricted to call-sites) UnwindPlan is '%s'\n",
3701 callsite_unwind_plan->GetSourceName().AsCString());
3703 UnwindPlanSP fast_unwind_plan =
3704 func_unwinders_sp->GetUnwindPlanFastUnwind(*target, *thread);
3705 if (fast_unwind_plan) {
3706 result.GetOutputStream().Printf(
3707 "Fast UnwindPlan is '%s'\n",
3708 fast_unwind_plan->GetSourceName().AsCString());
3711 result.GetOutputStream().Printf("\n");
3713 UnwindPlanSP assembly_sp =
3714 func_unwinders_sp->GetAssemblyUnwindPlan(*target, *thread);
3715 if (assembly_sp) {
3716 result.GetOutputStream().Printf(
3717 "Assembly language inspection UnwindPlan:\n");
3718 assembly_sp->Dump(result.GetOutputStream(), thread.get(),
3719 LLDB_INVALID_ADDRESS);
3720 result.GetOutputStream().Printf("\n");
3723 UnwindPlanSP of_unwind_sp =
3724 func_unwinders_sp->GetObjectFileUnwindPlan(*target);
3725 if (of_unwind_sp) {
3726 result.GetOutputStream().Printf("object file UnwindPlan:\n");
3727 of_unwind_sp->Dump(result.GetOutputStream(), thread.get(),
3728 LLDB_INVALID_ADDRESS);
3729 result.GetOutputStream().Printf("\n");
3732 UnwindPlanSP of_unwind_augmented_sp =
3733 func_unwinders_sp->GetObjectFileAugmentedUnwindPlan(*target, *thread);
3734 if (of_unwind_augmented_sp) {
3735 result.GetOutputStream().Printf("object file augmented UnwindPlan:\n");
3736 of_unwind_augmented_sp->Dump(result.GetOutputStream(), thread.get(),
3737 LLDB_INVALID_ADDRESS);
3738 result.GetOutputStream().Printf("\n");
3741 UnwindPlanSP ehframe_sp =
3742 func_unwinders_sp->GetEHFrameUnwindPlan(*target);
3743 if (ehframe_sp) {
3744 result.GetOutputStream().Printf("eh_frame UnwindPlan:\n");
3745 ehframe_sp->Dump(result.GetOutputStream(), thread.get(),
3746 LLDB_INVALID_ADDRESS);
3747 result.GetOutputStream().Printf("\n");
3750 UnwindPlanSP ehframe_augmented_sp =
3751 func_unwinders_sp->GetEHFrameAugmentedUnwindPlan(*target, *thread);
3752 if (ehframe_augmented_sp) {
3753 result.GetOutputStream().Printf("eh_frame augmented UnwindPlan:\n");
3754 ehframe_augmented_sp->Dump(result.GetOutputStream(), thread.get(),
3755 LLDB_INVALID_ADDRESS);
3756 result.GetOutputStream().Printf("\n");
3759 if (UnwindPlanSP plan_sp =
3760 func_unwinders_sp->GetDebugFrameUnwindPlan(*target)) {
3761 result.GetOutputStream().Printf("debug_frame UnwindPlan:\n");
3762 plan_sp->Dump(result.GetOutputStream(), thread.get(),
3763 LLDB_INVALID_ADDRESS);
3764 result.GetOutputStream().Printf("\n");
3767 if (UnwindPlanSP plan_sp =
3768 func_unwinders_sp->GetDebugFrameAugmentedUnwindPlan(*target,
3769 *thread)) {
3770 result.GetOutputStream().Printf("debug_frame augmented UnwindPlan:\n");
3771 plan_sp->Dump(result.GetOutputStream(), thread.get(),
3772 LLDB_INVALID_ADDRESS);
3773 result.GetOutputStream().Printf("\n");
3776 UnwindPlanSP arm_unwind_sp =
3777 func_unwinders_sp->GetArmUnwindUnwindPlan(*target);
3778 if (arm_unwind_sp) {
3779 result.GetOutputStream().Printf("ARM.exidx unwind UnwindPlan:\n");
3780 arm_unwind_sp->Dump(result.GetOutputStream(), thread.get(),
3781 LLDB_INVALID_ADDRESS);
3782 result.GetOutputStream().Printf("\n");
3785 if (UnwindPlanSP symfile_plan_sp =
3786 func_unwinders_sp->GetSymbolFileUnwindPlan(*thread)) {
3787 result.GetOutputStream().Printf("Symbol file UnwindPlan:\n");
3788 symfile_plan_sp->Dump(result.GetOutputStream(), thread.get(),
3789 LLDB_INVALID_ADDRESS);
3790 result.GetOutputStream().Printf("\n");
3793 UnwindPlanSP compact_unwind_sp =
3794 func_unwinders_sp->GetCompactUnwindUnwindPlan(*target);
3795 if (compact_unwind_sp) {
3796 result.GetOutputStream().Printf("Compact unwind UnwindPlan:\n");
3797 compact_unwind_sp->Dump(result.GetOutputStream(), thread.get(),
3798 LLDB_INVALID_ADDRESS);
3799 result.GetOutputStream().Printf("\n");
3802 if (fast_unwind_plan) {
3803 result.GetOutputStream().Printf("Fast UnwindPlan:\n");
3804 fast_unwind_plan->Dump(result.GetOutputStream(), thread.get(),
3805 LLDB_INVALID_ADDRESS);
3806 result.GetOutputStream().Printf("\n");
3809 ABISP abi_sp = process->GetABI();
3810 if (abi_sp) {
3811 UnwindPlan arch_default(lldb::eRegisterKindGeneric);
3812 if (abi_sp->CreateDefaultUnwindPlan(arch_default)) {
3813 result.GetOutputStream().Printf("Arch default UnwindPlan:\n");
3814 arch_default.Dump(result.GetOutputStream(), thread.get(),
3815 LLDB_INVALID_ADDRESS);
3816 result.GetOutputStream().Printf("\n");
3819 UnwindPlan arch_entry(lldb::eRegisterKindGeneric);
3820 if (abi_sp->CreateFunctionEntryUnwindPlan(arch_entry)) {
3821 result.GetOutputStream().Printf(
3822 "Arch default at entry point UnwindPlan:\n");
3823 arch_entry.Dump(result.GetOutputStream(), thread.get(),
3824 LLDB_INVALID_ADDRESS);
3825 result.GetOutputStream().Printf("\n");
3829 result.GetOutputStream().Printf("\n");
3833 CommandOptions m_options;
3836 // Lookup information in images
3837 #define LLDB_OPTIONS_target_modules_lookup
3838 #include "CommandOptions.inc"
3840 class CommandObjectTargetModulesLookup : public CommandObjectParsed {
3841 public:
3842 enum {
3843 eLookupTypeInvalid = -1,
3844 eLookupTypeAddress = 0,
3845 eLookupTypeSymbol,
3846 eLookupTypeFileLine, // Line is optional
3847 eLookupTypeFunction,
3848 eLookupTypeFunctionOrSymbol,
3849 eLookupTypeType,
3850 kNumLookupTypes
3853 class CommandOptions : public Options {
3854 public:
3855 CommandOptions() { OptionParsingStarting(nullptr); }
3857 ~CommandOptions() override = default;
3859 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
3860 ExecutionContext *execution_context) override {
3861 Status error;
3863 const int short_option = m_getopt_table[option_idx].val;
3865 switch (short_option) {
3866 case 'a': {
3867 m_type = eLookupTypeAddress;
3868 m_addr = OptionArgParser::ToAddress(execution_context, option_arg,
3869 LLDB_INVALID_ADDRESS, &error);
3870 } break;
3872 case 'o':
3873 if (option_arg.getAsInteger(0, m_offset))
3874 error.SetErrorStringWithFormat("invalid offset string '%s'",
3875 option_arg.str().c_str());
3876 break;
3878 case 's':
3879 m_str = std::string(option_arg);
3880 m_type = eLookupTypeSymbol;
3881 break;
3883 case 'f':
3884 m_file.SetFile(option_arg, FileSpec::Style::native);
3885 m_type = eLookupTypeFileLine;
3886 break;
3888 case 'i':
3889 m_include_inlines = false;
3890 break;
3892 case 'l':
3893 if (option_arg.getAsInteger(0, m_line_number))
3894 error.SetErrorStringWithFormat("invalid line number string '%s'",
3895 option_arg.str().c_str());
3896 else if (m_line_number == 0)
3897 error.SetErrorString("zero is an invalid line number");
3898 m_type = eLookupTypeFileLine;
3899 break;
3901 case 'F':
3902 m_str = std::string(option_arg);
3903 m_type = eLookupTypeFunction;
3904 break;
3906 case 'n':
3907 m_str = std::string(option_arg);
3908 m_type = eLookupTypeFunctionOrSymbol;
3909 break;
3911 case 't':
3912 m_str = std::string(option_arg);
3913 m_type = eLookupTypeType;
3914 break;
3916 case 'v':
3917 m_verbose = true;
3918 break;
3920 case 'A':
3921 m_print_all = true;
3922 break;
3924 case 'r':
3925 m_use_regex = true;
3926 break;
3928 case '\x01':
3929 m_all_ranges = true;
3930 break;
3931 default:
3932 llvm_unreachable("Unimplemented option");
3935 return error;
3938 void OptionParsingStarting(ExecutionContext *execution_context) override {
3939 m_type = eLookupTypeInvalid;
3940 m_str.clear();
3941 m_file.Clear();
3942 m_addr = LLDB_INVALID_ADDRESS;
3943 m_offset = 0;
3944 m_line_number = 0;
3945 m_use_regex = false;
3946 m_include_inlines = true;
3947 m_all_ranges = false;
3948 m_verbose = false;
3949 m_print_all = false;
3952 Status OptionParsingFinished(ExecutionContext *execution_context) override {
3953 Status status;
3954 if (m_all_ranges && !m_verbose) {
3955 status.SetErrorString("--show-variable-ranges must be used in "
3956 "conjunction with --verbose.");
3958 return status;
3961 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
3962 return llvm::ArrayRef(g_target_modules_lookup_options);
3965 int m_type; // Should be a eLookupTypeXXX enum after parsing options
3966 std::string m_str; // Holds name lookup
3967 FileSpec m_file; // Files for file lookups
3968 lldb::addr_t m_addr; // Holds the address to lookup
3969 lldb::addr_t
3970 m_offset; // Subtract this offset from m_addr before doing lookups.
3971 uint32_t m_line_number; // Line number for file+line lookups
3972 bool m_use_regex; // Name lookups in m_str are regular expressions.
3973 bool m_include_inlines; // Check for inline entries when looking up by
3974 // file/line.
3975 bool m_all_ranges; // Print all ranges or single range.
3976 bool m_verbose; // Enable verbose lookup info
3977 bool m_print_all; // Print all matches, even in cases where there's a best
3978 // match.
3981 CommandObjectTargetModulesLookup(CommandInterpreter &interpreter)
3982 : CommandObjectParsed(interpreter, "target modules lookup",
3983 "Look up information within executable and "
3984 "dependent shared library images.",
3985 nullptr, eCommandRequiresTarget) {
3986 CommandArgumentEntry arg;
3987 CommandArgumentData file_arg;
3989 // Define the first (and only) variant of this arg.
3990 file_arg.arg_type = eArgTypeFilename;
3991 file_arg.arg_repetition = eArgRepeatStar;
3993 // There is only one variant this argument could be; put it into the
3994 // argument entry.
3995 arg.push_back(file_arg);
3997 // Push the data for the first argument into the m_arguments vector.
3998 m_arguments.push_back(arg);
4001 ~CommandObjectTargetModulesLookup() override = default;
4003 Options *GetOptions() override { return &m_options; }
4005 bool LookupHere(CommandInterpreter &interpreter, CommandReturnObject &result,
4006 bool &syntax_error) {
4007 switch (m_options.m_type) {
4008 case eLookupTypeAddress:
4009 case eLookupTypeFileLine:
4010 case eLookupTypeFunction:
4011 case eLookupTypeFunctionOrSymbol:
4012 case eLookupTypeSymbol:
4013 default:
4014 return false;
4015 case eLookupTypeType:
4016 break;
4019 StackFrameSP frame = m_exe_ctx.GetFrameSP();
4021 if (!frame)
4022 return false;
4024 const SymbolContext &sym_ctx(frame->GetSymbolContext(eSymbolContextModule));
4026 if (!sym_ctx.module_sp)
4027 return false;
4029 switch (m_options.m_type) {
4030 default:
4031 return false;
4032 case eLookupTypeType:
4033 if (!m_options.m_str.empty()) {
4034 if (LookupTypeHere(&GetSelectedTarget(), m_interpreter,
4035 result.GetOutputStream(), *sym_ctx.module_sp,
4036 m_options.m_str.c_str(), m_options.m_use_regex)) {
4037 result.SetStatus(eReturnStatusSuccessFinishResult);
4038 return true;
4041 break;
4044 return false;
4047 bool LookupInModule(CommandInterpreter &interpreter, Module *module,
4048 CommandReturnObject &result, bool &syntax_error) {
4049 switch (m_options.m_type) {
4050 case eLookupTypeAddress:
4051 if (m_options.m_addr != LLDB_INVALID_ADDRESS) {
4052 if (LookupAddressInModule(
4053 m_interpreter, result.GetOutputStream(), module,
4054 eSymbolContextEverything |
4055 (m_options.m_verbose
4056 ? static_cast<int>(eSymbolContextVariable)
4057 : 0),
4058 m_options.m_addr, m_options.m_offset, m_options.m_verbose,
4059 m_options.m_all_ranges)) {
4060 result.SetStatus(eReturnStatusSuccessFinishResult);
4061 return true;
4064 break;
4066 case eLookupTypeSymbol:
4067 if (!m_options.m_str.empty()) {
4068 if (LookupSymbolInModule(m_interpreter, result.GetOutputStream(),
4069 module, m_options.m_str.c_str(),
4070 m_options.m_use_regex, m_options.m_verbose,
4071 m_options.m_all_ranges)) {
4072 result.SetStatus(eReturnStatusSuccessFinishResult);
4073 return true;
4076 break;
4078 case eLookupTypeFileLine:
4079 if (m_options.m_file) {
4080 if (LookupFileAndLineInModule(
4081 m_interpreter, result.GetOutputStream(), module,
4082 m_options.m_file, m_options.m_line_number,
4083 m_options.m_include_inlines, m_options.m_verbose,
4084 m_options.m_all_ranges)) {
4085 result.SetStatus(eReturnStatusSuccessFinishResult);
4086 return true;
4089 break;
4091 case eLookupTypeFunctionOrSymbol:
4092 case eLookupTypeFunction:
4093 if (!m_options.m_str.empty()) {
4094 ModuleFunctionSearchOptions function_options;
4095 function_options.include_symbols =
4096 m_options.m_type == eLookupTypeFunctionOrSymbol;
4097 function_options.include_inlines = m_options.m_include_inlines;
4099 if (LookupFunctionInModule(m_interpreter, result.GetOutputStream(),
4100 module, m_options.m_str.c_str(),
4101 m_options.m_use_regex, function_options,
4102 m_options.m_verbose,
4103 m_options.m_all_ranges)) {
4104 result.SetStatus(eReturnStatusSuccessFinishResult);
4105 return true;
4108 break;
4110 case eLookupTypeType:
4111 if (!m_options.m_str.empty()) {
4112 if (LookupTypeInModule(
4113 &GetSelectedTarget(), m_interpreter, result.GetOutputStream(),
4114 module, m_options.m_str.c_str(), m_options.m_use_regex)) {
4115 result.SetStatus(eReturnStatusSuccessFinishResult);
4116 return true;
4119 break;
4121 default:
4122 m_options.GenerateOptionUsage(
4123 result.GetErrorStream(), *this,
4124 GetCommandInterpreter().GetDebugger().GetTerminalWidth());
4125 syntax_error = true;
4126 break;
4129 result.SetStatus(eReturnStatusFailed);
4130 return false;
4133 protected:
4134 void DoExecute(Args &command, CommandReturnObject &result) override {
4135 Target *target = &GetSelectedTarget();
4136 bool syntax_error = false;
4137 uint32_t i;
4138 uint32_t num_successful_lookups = 0;
4139 uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
4140 result.GetOutputStream().SetAddressByteSize(addr_byte_size);
4141 result.GetErrorStream().SetAddressByteSize(addr_byte_size);
4142 // Dump all sections for all modules images
4144 if (command.GetArgumentCount() == 0) {
4145 ModuleSP current_module;
4147 // Where it is possible to look in the current symbol context first,
4148 // try that. If this search was successful and --all was not passed,
4149 // don't print anything else.
4150 if (LookupHere(m_interpreter, result, syntax_error)) {
4151 result.GetOutputStream().EOL();
4152 num_successful_lookups++;
4153 if (!m_options.m_print_all) {
4154 result.SetStatus(eReturnStatusSuccessFinishResult);
4155 return;
4159 // Dump all sections for all other modules
4161 const ModuleList &target_modules = target->GetImages();
4162 std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
4163 if (target_modules.GetSize() == 0) {
4164 result.AppendError("the target has no associated executable images");
4165 return;
4168 for (ModuleSP module_sp : target_modules.ModulesNoLocking()) {
4169 if (module_sp != current_module &&
4170 LookupInModule(m_interpreter, module_sp.get(), result,
4171 syntax_error)) {
4172 result.GetOutputStream().EOL();
4173 num_successful_lookups++;
4176 } else {
4177 // Dump specified images (by basename or fullpath)
4178 const char *arg_cstr;
4179 for (i = 0; (arg_cstr = command.GetArgumentAtIndex(i)) != nullptr &&
4180 !syntax_error;
4181 ++i) {
4182 ModuleList module_list;
4183 const size_t num_matches =
4184 FindModulesByName(target, arg_cstr, module_list, false);
4185 if (num_matches > 0) {
4186 for (size_t j = 0; j < num_matches; ++j) {
4187 Module *module = module_list.GetModulePointerAtIndex(j);
4188 if (module) {
4189 if (LookupInModule(m_interpreter, module, result, syntax_error)) {
4190 result.GetOutputStream().EOL();
4191 num_successful_lookups++;
4195 } else
4196 result.AppendWarningWithFormat(
4197 "Unable to find an image that matches '%s'.\n", arg_cstr);
4201 if (num_successful_lookups > 0)
4202 result.SetStatus(eReturnStatusSuccessFinishResult);
4203 else
4204 result.SetStatus(eReturnStatusFailed);
4207 CommandOptions m_options;
4210 #pragma mark CommandObjectMultiwordImageSearchPaths
4212 // CommandObjectMultiwordImageSearchPaths
4214 class CommandObjectTargetModulesImageSearchPaths
4215 : public CommandObjectMultiword {
4216 public:
4217 CommandObjectTargetModulesImageSearchPaths(CommandInterpreter &interpreter)
4218 : CommandObjectMultiword(
4219 interpreter, "target modules search-paths",
4220 "Commands for managing module search paths for a target.",
4221 "target modules search-paths <subcommand> [<subcommand-options>]") {
4222 LoadSubCommand(
4223 "add", CommandObjectSP(
4224 new CommandObjectTargetModulesSearchPathsAdd(interpreter)));
4225 LoadSubCommand(
4226 "clear", CommandObjectSP(new CommandObjectTargetModulesSearchPathsClear(
4227 interpreter)));
4228 LoadSubCommand(
4229 "insert",
4230 CommandObjectSP(
4231 new CommandObjectTargetModulesSearchPathsInsert(interpreter)));
4232 LoadSubCommand(
4233 "list", CommandObjectSP(new CommandObjectTargetModulesSearchPathsList(
4234 interpreter)));
4235 LoadSubCommand(
4236 "query", CommandObjectSP(new CommandObjectTargetModulesSearchPathsQuery(
4237 interpreter)));
4240 ~CommandObjectTargetModulesImageSearchPaths() override = default;
4243 #pragma mark CommandObjectTargetModules
4245 // CommandObjectTargetModules
4247 class CommandObjectTargetModules : public CommandObjectMultiword {
4248 public:
4249 // Constructors and Destructors
4250 CommandObjectTargetModules(CommandInterpreter &interpreter)
4251 : CommandObjectMultiword(interpreter, "target modules",
4252 "Commands for accessing information for one or "
4253 "more target modules.",
4254 "target modules <sub-command> ...") {
4255 LoadSubCommand(
4256 "add", CommandObjectSP(new CommandObjectTargetModulesAdd(interpreter)));
4257 LoadSubCommand("load", CommandObjectSP(new CommandObjectTargetModulesLoad(
4258 interpreter)));
4259 LoadSubCommand("dump", CommandObjectSP(new CommandObjectTargetModulesDump(
4260 interpreter)));
4261 LoadSubCommand("list", CommandObjectSP(new CommandObjectTargetModulesList(
4262 interpreter)));
4263 LoadSubCommand(
4264 "lookup",
4265 CommandObjectSP(new CommandObjectTargetModulesLookup(interpreter)));
4266 LoadSubCommand(
4267 "search-paths",
4268 CommandObjectSP(
4269 new CommandObjectTargetModulesImageSearchPaths(interpreter)));
4270 LoadSubCommand(
4271 "show-unwind",
4272 CommandObjectSP(new CommandObjectTargetModulesShowUnwind(interpreter)));
4275 ~CommandObjectTargetModules() override = default;
4277 private:
4278 // For CommandObjectTargetModules only
4279 CommandObjectTargetModules(const CommandObjectTargetModules &) = delete;
4280 const CommandObjectTargetModules &
4281 operator=(const CommandObjectTargetModules &) = delete;
4284 class CommandObjectTargetSymbolsAdd : public CommandObjectParsed {
4285 public:
4286 CommandObjectTargetSymbolsAdd(CommandInterpreter &interpreter)
4287 : CommandObjectParsed(
4288 interpreter, "target symbols add",
4289 "Add a debug symbol file to one of the target's current modules by "
4290 "specifying a path to a debug symbols file or by using the options "
4291 "to specify a module.",
4292 "target symbols add <cmd-options> [<symfile>]",
4293 eCommandRequiresTarget),
4294 m_file_option(
4295 LLDB_OPT_SET_1, false, "shlib", 's', lldb::eModuleCompletion,
4296 eArgTypeShlibName,
4297 "Locate the debug symbols for the shared library specified by "
4298 "name."),
4299 m_current_frame_option(
4300 LLDB_OPT_SET_2, false, "frame", 'F',
4301 "Locate the debug symbols for the currently selected frame.", false,
4302 true),
4303 m_current_stack_option(LLDB_OPT_SET_2, false, "stack", 'S',
4304 "Locate the debug symbols for every frame in "
4305 "the current call stack.",
4306 false, true)
4309 m_option_group.Append(&m_uuid_option_group, LLDB_OPT_SET_ALL,
4310 LLDB_OPT_SET_1);
4311 m_option_group.Append(&m_file_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
4312 m_option_group.Append(&m_current_frame_option, LLDB_OPT_SET_2,
4313 LLDB_OPT_SET_2);
4314 m_option_group.Append(&m_current_stack_option, LLDB_OPT_SET_2,
4315 LLDB_OPT_SET_2);
4316 m_option_group.Finalize();
4317 CommandArgumentData module_arg{eArgTypeShlibName, eArgRepeatPlain};
4318 m_arguments.push_back({module_arg});
4321 ~CommandObjectTargetSymbolsAdd() override = default;
4323 void
4324 HandleArgumentCompletion(CompletionRequest &request,
4325 OptionElementVector &opt_element_vector) override {
4326 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
4327 GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr);
4330 Options *GetOptions() override { return &m_option_group; }
4332 protected:
4333 bool AddModuleSymbols(Target *target, ModuleSpec &module_spec, bool &flush,
4334 CommandReturnObject &result) {
4335 const FileSpec &symbol_fspec = module_spec.GetSymbolFileSpec();
4336 if (!symbol_fspec) {
4337 result.AppendError(
4338 "one or more executable image paths must be specified");
4339 return false;
4342 char symfile_path[PATH_MAX];
4343 symbol_fspec.GetPath(symfile_path, sizeof(symfile_path));
4345 if (!module_spec.GetUUID().IsValid()) {
4346 if (!module_spec.GetFileSpec() && !module_spec.GetPlatformFileSpec())
4347 module_spec.GetFileSpec().SetFilename(symbol_fspec.GetFilename());
4350 // Now module_spec represents a symbol file for a module that might exist
4351 // in the current target. Let's find possible matches.
4352 ModuleList matching_modules;
4354 // First extract all module specs from the symbol file
4355 lldb_private::ModuleSpecList symfile_module_specs;
4356 if (ObjectFile::GetModuleSpecifications(module_spec.GetSymbolFileSpec(),
4357 0, 0, symfile_module_specs)) {
4358 // Now extract the module spec that matches the target architecture
4359 ModuleSpec target_arch_module_spec;
4360 ModuleSpec symfile_module_spec;
4361 target_arch_module_spec.GetArchitecture() = target->GetArchitecture();
4362 if (symfile_module_specs.FindMatchingModuleSpec(target_arch_module_spec,
4363 symfile_module_spec)) {
4364 if (symfile_module_spec.GetUUID().IsValid()) {
4365 // It has a UUID, look for this UUID in the target modules
4366 ModuleSpec symfile_uuid_module_spec;
4367 symfile_uuid_module_spec.GetUUID() = symfile_module_spec.GetUUID();
4368 target->GetImages().FindModules(symfile_uuid_module_spec,
4369 matching_modules);
4373 if (matching_modules.IsEmpty()) {
4374 // No matches yet. Iterate through the module specs to find a UUID
4375 // value that we can match up to an image in our target.
4376 const size_t num_symfile_module_specs = symfile_module_specs.GetSize();
4377 for (size_t i = 0;
4378 i < num_symfile_module_specs && matching_modules.IsEmpty(); ++i) {
4379 if (symfile_module_specs.GetModuleSpecAtIndex(
4380 i, symfile_module_spec)) {
4381 if (symfile_module_spec.GetUUID().IsValid()) {
4382 // It has a UUID. Look for this UUID in the target modules.
4383 ModuleSpec symfile_uuid_module_spec;
4384 symfile_uuid_module_spec.GetUUID() =
4385 symfile_module_spec.GetUUID();
4386 target->GetImages().FindModules(symfile_uuid_module_spec,
4387 matching_modules);
4394 // Just try to match up the file by basename if we have no matches at
4395 // this point. For example, module foo might have symbols in foo.debug.
4396 if (matching_modules.IsEmpty())
4397 target->GetImages().FindModules(module_spec, matching_modules);
4399 while (matching_modules.IsEmpty()) {
4400 ConstString filename_no_extension(
4401 module_spec.GetFileSpec().GetFileNameStrippingExtension());
4402 // Empty string returned, let's bail
4403 if (!filename_no_extension)
4404 break;
4406 // Check if there was no extension to strip and the basename is the same
4407 if (filename_no_extension == module_spec.GetFileSpec().GetFilename())
4408 break;
4410 // Replace basename with one fewer extension
4411 module_spec.GetFileSpec().SetFilename(filename_no_extension);
4412 target->GetImages().FindModules(module_spec, matching_modules);
4415 if (matching_modules.GetSize() > 1) {
4416 result.AppendErrorWithFormat("multiple modules match symbol file '%s', "
4417 "use the --uuid option to resolve the "
4418 "ambiguity.\n",
4419 symfile_path);
4420 return false;
4423 if (matching_modules.GetSize() == 1) {
4424 ModuleSP module_sp(matching_modules.GetModuleAtIndex(0));
4426 // The module has not yet created its symbol vendor, we can just give
4427 // the existing target module the symfile path to use for when it
4428 // decides to create it!
4429 module_sp->SetSymbolFileFileSpec(symbol_fspec);
4431 SymbolFile *symbol_file =
4432 module_sp->GetSymbolFile(true, &result.GetErrorStream());
4433 if (symbol_file) {
4434 ObjectFile *object_file = symbol_file->GetObjectFile();
4435 if (object_file && object_file->GetFileSpec() == symbol_fspec) {
4436 // Provide feedback that the symfile has been successfully added.
4437 const FileSpec &module_fs = module_sp->GetFileSpec();
4438 result.AppendMessageWithFormat(
4439 "symbol file '%s' has been added to '%s'\n", symfile_path,
4440 module_fs.GetPath().c_str());
4442 // Let clients know something changed in the module if it is
4443 // currently loaded
4444 ModuleList module_list;
4445 module_list.Append(module_sp);
4446 target->SymbolsDidLoad(module_list);
4448 // Make sure we load any scripting resources that may be embedded
4449 // in the debug info files in case the platform supports that.
4450 Status error;
4451 StreamString feedback_stream;
4452 module_sp->LoadScriptingResourceInTarget(target, error,
4453 feedback_stream);
4454 if (error.Fail() && error.AsCString())
4455 result.AppendWarningWithFormat(
4456 "unable to load scripting data for module %s - error "
4457 "reported was %s",
4458 module_sp->GetFileSpec()
4459 .GetFileNameStrippingExtension()
4460 .GetCString(),
4461 error.AsCString());
4462 else if (feedback_stream.GetSize())
4463 result.AppendWarning(feedback_stream.GetData());
4465 flush = true;
4466 result.SetStatus(eReturnStatusSuccessFinishResult);
4467 return true;
4470 // Clear the symbol file spec if anything went wrong
4471 module_sp->SetSymbolFileFileSpec(FileSpec());
4474 StreamString ss_symfile_uuid;
4475 if (module_spec.GetUUID().IsValid()) {
4476 ss_symfile_uuid << " (";
4477 module_spec.GetUUID().Dump(ss_symfile_uuid);
4478 ss_symfile_uuid << ')';
4480 result.AppendErrorWithFormat(
4481 "symbol file '%s'%s does not match any existing module%s\n",
4482 symfile_path, ss_symfile_uuid.GetData(),
4483 !llvm::sys::fs::is_regular_file(symbol_fspec.GetPath())
4484 ? "\n please specify the full path to the symbol file"
4485 : "");
4486 return false;
4489 bool DownloadObjectAndSymbolFile(ModuleSpec &module_spec,
4490 CommandReturnObject &result, bool &flush) {
4491 Status error;
4492 if (Symbols::DownloadObjectAndSymbolFile(module_spec, error)) {
4493 if (module_spec.GetSymbolFileSpec())
4494 return AddModuleSymbols(m_exe_ctx.GetTargetPtr(), module_spec, flush,
4495 result);
4496 } else {
4497 result.SetError(error);
4499 return false;
4502 bool AddSymbolsForUUID(CommandReturnObject &result, bool &flush) {
4503 assert(m_uuid_option_group.GetOptionValue().OptionWasSet());
4505 ModuleSpec module_spec;
4506 module_spec.GetUUID() =
4507 m_uuid_option_group.GetOptionValue().GetCurrentValue();
4509 if (!DownloadObjectAndSymbolFile(module_spec, result, flush)) {
4510 StreamString error_strm;
4511 error_strm.PutCString("unable to find debug symbols for UUID ");
4512 module_spec.GetUUID().Dump(error_strm);
4513 result.AppendError(error_strm.GetString());
4514 return false;
4517 return true;
4520 bool AddSymbolsForFile(CommandReturnObject &result, bool &flush) {
4521 assert(m_file_option.GetOptionValue().OptionWasSet());
4523 ModuleSpec module_spec;
4524 module_spec.GetFileSpec() =
4525 m_file_option.GetOptionValue().GetCurrentValue();
4527 Target *target = m_exe_ctx.GetTargetPtr();
4528 ModuleSP module_sp(target->GetImages().FindFirstModule(module_spec));
4529 if (module_sp) {
4530 module_spec.GetFileSpec() = module_sp->GetFileSpec();
4531 module_spec.GetPlatformFileSpec() = module_sp->GetPlatformFileSpec();
4532 module_spec.GetUUID() = module_sp->GetUUID();
4533 module_spec.GetArchitecture() = module_sp->GetArchitecture();
4534 } else {
4535 module_spec.GetArchitecture() = target->GetArchitecture();
4538 if (!DownloadObjectAndSymbolFile(module_spec, result, flush)) {
4539 StreamString error_strm;
4540 error_strm.PutCString(
4541 "unable to find debug symbols for the executable file ");
4542 error_strm << module_spec.GetFileSpec();
4543 result.AppendError(error_strm.GetString());
4544 return false;
4547 return true;
4550 bool AddSymbolsForFrame(CommandReturnObject &result, bool &flush) {
4551 assert(m_current_frame_option.GetOptionValue().OptionWasSet());
4553 Process *process = m_exe_ctx.GetProcessPtr();
4554 if (!process) {
4555 result.AppendError(
4556 "a process must exist in order to use the --frame option");
4557 return false;
4560 const StateType process_state = process->GetState();
4561 if (!StateIsStoppedState(process_state, true)) {
4562 result.AppendErrorWithFormat("process is not stopped: %s",
4563 StateAsCString(process_state));
4564 return false;
4567 StackFrame *frame = m_exe_ctx.GetFramePtr();
4568 if (!frame) {
4569 result.AppendError("invalid current frame");
4570 return false;
4573 ModuleSP frame_module_sp(
4574 frame->GetSymbolContext(eSymbolContextModule).module_sp);
4575 if (!frame_module_sp) {
4576 result.AppendError("frame has no module");
4577 return false;
4580 ModuleSpec module_spec;
4581 module_spec.GetUUID() = frame_module_sp->GetUUID();
4583 if (FileSystem::Instance().Exists(frame_module_sp->GetPlatformFileSpec())) {
4584 module_spec.GetArchitecture() = frame_module_sp->GetArchitecture();
4585 module_spec.GetFileSpec() = frame_module_sp->GetPlatformFileSpec();
4588 if (!DownloadObjectAndSymbolFile(module_spec, result, flush)) {
4589 result.AppendError("unable to find debug symbols for the current frame");
4590 return false;
4593 return true;
4596 bool AddSymbolsForStack(CommandReturnObject &result, bool &flush) {
4597 assert(m_current_stack_option.GetOptionValue().OptionWasSet());
4599 Process *process = m_exe_ctx.GetProcessPtr();
4600 if (!process) {
4601 result.AppendError(
4602 "a process must exist in order to use the --stack option");
4603 return false;
4606 const StateType process_state = process->GetState();
4607 if (!StateIsStoppedState(process_state, true)) {
4608 result.AppendErrorWithFormat("process is not stopped: %s",
4609 StateAsCString(process_state));
4610 return false;
4613 Thread *thread = m_exe_ctx.GetThreadPtr();
4614 if (!thread) {
4615 result.AppendError("invalid current thread");
4616 return false;
4619 bool symbols_found = false;
4620 uint32_t frame_count = thread->GetStackFrameCount();
4621 for (uint32_t i = 0; i < frame_count; ++i) {
4622 lldb::StackFrameSP frame_sp = thread->GetStackFrameAtIndex(i);
4624 ModuleSP frame_module_sp(
4625 frame_sp->GetSymbolContext(eSymbolContextModule).module_sp);
4626 if (!frame_module_sp)
4627 continue;
4629 ModuleSpec module_spec;
4630 module_spec.GetUUID() = frame_module_sp->GetUUID();
4632 if (FileSystem::Instance().Exists(
4633 frame_module_sp->GetPlatformFileSpec())) {
4634 module_spec.GetArchitecture() = frame_module_sp->GetArchitecture();
4635 module_spec.GetFileSpec() = frame_module_sp->GetPlatformFileSpec();
4638 bool current_frame_flush = false;
4639 if (DownloadObjectAndSymbolFile(module_spec, result, current_frame_flush))
4640 symbols_found = true;
4641 flush |= current_frame_flush;
4644 if (!symbols_found) {
4645 result.AppendError(
4646 "unable to find debug symbols in the current call stack");
4647 return false;
4650 return true;
4653 void DoExecute(Args &args, CommandReturnObject &result) override {
4654 Target *target = m_exe_ctx.GetTargetPtr();
4655 result.SetStatus(eReturnStatusFailed);
4656 bool flush = false;
4657 ModuleSpec module_spec;
4658 const bool uuid_option_set =
4659 m_uuid_option_group.GetOptionValue().OptionWasSet();
4660 const bool file_option_set = m_file_option.GetOptionValue().OptionWasSet();
4661 const bool frame_option_set =
4662 m_current_frame_option.GetOptionValue().OptionWasSet();
4663 const bool stack_option_set =
4664 m_current_stack_option.GetOptionValue().OptionWasSet();
4665 const size_t argc = args.GetArgumentCount();
4667 if (argc == 0) {
4668 if (uuid_option_set)
4669 AddSymbolsForUUID(result, flush);
4670 else if (file_option_set)
4671 AddSymbolsForFile(result, flush);
4672 else if (frame_option_set)
4673 AddSymbolsForFrame(result, flush);
4674 else if (stack_option_set)
4675 AddSymbolsForStack(result, flush);
4676 else
4677 result.AppendError("one or more symbol file paths must be specified, "
4678 "or options must be specified");
4679 } else {
4680 if (uuid_option_set) {
4681 result.AppendError("specify either one or more paths to symbol files "
4682 "or use the --uuid option without arguments");
4683 } else if (frame_option_set) {
4684 result.AppendError("specify either one or more paths to symbol files "
4685 "or use the --frame option without arguments");
4686 } else if (file_option_set && argc > 1) {
4687 result.AppendError("specify at most one symbol file path when "
4688 "--shlib option is set");
4689 } else {
4690 PlatformSP platform_sp(target->GetPlatform());
4692 for (auto &entry : args.entries()) {
4693 if (!entry.ref().empty()) {
4694 auto &symbol_file_spec = module_spec.GetSymbolFileSpec();
4695 symbol_file_spec.SetFile(entry.ref(), FileSpec::Style::native);
4696 FileSystem::Instance().Resolve(symbol_file_spec);
4697 if (file_option_set) {
4698 module_spec.GetFileSpec() =
4699 m_file_option.GetOptionValue().GetCurrentValue();
4701 if (platform_sp) {
4702 FileSpec symfile_spec;
4703 if (platform_sp
4704 ->ResolveSymbolFile(*target, module_spec, symfile_spec)
4705 .Success())
4706 module_spec.GetSymbolFileSpec() = symfile_spec;
4709 bool symfile_exists =
4710 FileSystem::Instance().Exists(module_spec.GetSymbolFileSpec());
4712 if (symfile_exists) {
4713 if (!AddModuleSymbols(target, module_spec, flush, result))
4714 break;
4715 } else {
4716 std::string resolved_symfile_path =
4717 module_spec.GetSymbolFileSpec().GetPath();
4718 if (resolved_symfile_path != entry.ref()) {
4719 result.AppendErrorWithFormat(
4720 "invalid module path '%s' with resolved path '%s'\n",
4721 entry.c_str(), resolved_symfile_path.c_str());
4722 break;
4724 result.AppendErrorWithFormat("invalid module path '%s'\n",
4725 entry.c_str());
4726 break;
4733 if (flush) {
4734 Process *process = m_exe_ctx.GetProcessPtr();
4735 if (process)
4736 process->Flush();
4740 OptionGroupOptions m_option_group;
4741 OptionGroupUUID m_uuid_option_group;
4742 OptionGroupFile m_file_option;
4743 OptionGroupBoolean m_current_frame_option;
4744 OptionGroupBoolean m_current_stack_option;
4747 #pragma mark CommandObjectTargetSymbols
4749 // CommandObjectTargetSymbols
4751 class CommandObjectTargetSymbols : public CommandObjectMultiword {
4752 public:
4753 // Constructors and Destructors
4754 CommandObjectTargetSymbols(CommandInterpreter &interpreter)
4755 : CommandObjectMultiword(
4756 interpreter, "target symbols",
4757 "Commands for adding and managing debug symbol files.",
4758 "target symbols <sub-command> ...") {
4759 LoadSubCommand(
4760 "add", CommandObjectSP(new CommandObjectTargetSymbolsAdd(interpreter)));
4763 ~CommandObjectTargetSymbols() override = default;
4765 private:
4766 // For CommandObjectTargetModules only
4767 CommandObjectTargetSymbols(const CommandObjectTargetSymbols &) = delete;
4768 const CommandObjectTargetSymbols &
4769 operator=(const CommandObjectTargetSymbols &) = delete;
4772 #pragma mark CommandObjectTargetStopHookAdd
4774 // CommandObjectTargetStopHookAdd
4775 #define LLDB_OPTIONS_target_stop_hook_add
4776 #include "CommandOptions.inc"
4778 class CommandObjectTargetStopHookAdd : public CommandObjectParsed,
4779 public IOHandlerDelegateMultiline {
4780 public:
4781 class CommandOptions : public OptionGroup {
4782 public:
4783 CommandOptions() : m_line_end(UINT_MAX) {}
4785 ~CommandOptions() override = default;
4787 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
4788 return llvm::ArrayRef(g_target_stop_hook_add_options);
4791 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
4792 ExecutionContext *execution_context) override {
4793 Status error;
4794 const int short_option =
4795 g_target_stop_hook_add_options[option_idx].short_option;
4797 switch (short_option) {
4798 case 'c':
4799 m_class_name = std::string(option_arg);
4800 m_sym_ctx_specified = true;
4801 break;
4803 case 'e':
4804 if (option_arg.getAsInteger(0, m_line_end)) {
4805 error.SetErrorStringWithFormat("invalid end line number: \"%s\"",
4806 option_arg.str().c_str());
4807 break;
4809 m_sym_ctx_specified = true;
4810 break;
4812 case 'G': {
4813 bool value, success;
4814 value = OptionArgParser::ToBoolean(option_arg, false, &success);
4815 if (success) {
4816 m_auto_continue = value;
4817 } else
4818 error.SetErrorStringWithFormat(
4819 "invalid boolean value '%s' passed for -G option",
4820 option_arg.str().c_str());
4821 } break;
4822 case 'l':
4823 if (option_arg.getAsInteger(0, m_line_start)) {
4824 error.SetErrorStringWithFormat("invalid start line number: \"%s\"",
4825 option_arg.str().c_str());
4826 break;
4828 m_sym_ctx_specified = true;
4829 break;
4831 case 'i':
4832 m_no_inlines = true;
4833 break;
4835 case 'n':
4836 m_function_name = std::string(option_arg);
4837 m_func_name_type_mask |= eFunctionNameTypeAuto;
4838 m_sym_ctx_specified = true;
4839 break;
4841 case 'f':
4842 m_file_name = std::string(option_arg);
4843 m_sym_ctx_specified = true;
4844 break;
4846 case 's':
4847 m_module_name = std::string(option_arg);
4848 m_sym_ctx_specified = true;
4849 break;
4851 case 't':
4852 if (option_arg.getAsInteger(0, m_thread_id))
4853 error.SetErrorStringWithFormat("invalid thread id string '%s'",
4854 option_arg.str().c_str());
4855 m_thread_specified = true;
4856 break;
4858 case 'T':
4859 m_thread_name = std::string(option_arg);
4860 m_thread_specified = true;
4861 break;
4863 case 'q':
4864 m_queue_name = std::string(option_arg);
4865 m_thread_specified = true;
4866 break;
4868 case 'x':
4869 if (option_arg.getAsInteger(0, m_thread_index))
4870 error.SetErrorStringWithFormat("invalid thread index string '%s'",
4871 option_arg.str().c_str());
4872 m_thread_specified = true;
4873 break;
4875 case 'o':
4876 m_use_one_liner = true;
4877 m_one_liner.push_back(std::string(option_arg));
4878 break;
4880 default:
4881 llvm_unreachable("Unimplemented option");
4883 return error;
4886 void OptionParsingStarting(ExecutionContext *execution_context) override {
4887 m_class_name.clear();
4888 m_function_name.clear();
4889 m_line_start = 0;
4890 m_line_end = LLDB_INVALID_LINE_NUMBER;
4891 m_file_name.clear();
4892 m_module_name.clear();
4893 m_func_name_type_mask = eFunctionNameTypeAuto;
4894 m_thread_id = LLDB_INVALID_THREAD_ID;
4895 m_thread_index = UINT32_MAX;
4896 m_thread_name.clear();
4897 m_queue_name.clear();
4899 m_no_inlines = false;
4900 m_sym_ctx_specified = false;
4901 m_thread_specified = false;
4903 m_use_one_liner = false;
4904 m_one_liner.clear();
4905 m_auto_continue = false;
4908 std::string m_class_name;
4909 std::string m_function_name;
4910 uint32_t m_line_start = 0;
4911 uint32_t m_line_end = LLDB_INVALID_LINE_NUMBER;
4912 std::string m_file_name;
4913 std::string m_module_name;
4914 uint32_t m_func_name_type_mask =
4915 eFunctionNameTypeAuto; // A pick from lldb::FunctionNameType.
4916 lldb::tid_t m_thread_id = LLDB_INVALID_THREAD_ID;
4917 uint32_t m_thread_index = UINT32_MAX;
4918 std::string m_thread_name;
4919 std::string m_queue_name;
4920 bool m_sym_ctx_specified = false;
4921 bool m_no_inlines = false;
4922 bool m_thread_specified = false;
4923 // Instance variables to hold the values for one_liner options.
4924 bool m_use_one_liner = false;
4925 std::vector<std::string> m_one_liner;
4927 bool m_auto_continue = false;
4930 CommandObjectTargetStopHookAdd(CommandInterpreter &interpreter)
4931 : CommandObjectParsed(interpreter, "target stop-hook add",
4932 "Add a hook to be executed when the target stops."
4933 "The hook can either be a list of commands or an "
4934 "appropriately defined Python class. You can also "
4935 "add filters so the hook only runs a certain stop "
4936 "points.",
4937 "target stop-hook add"),
4938 IOHandlerDelegateMultiline("DONE",
4939 IOHandlerDelegate::Completion::LLDBCommand),
4940 m_python_class_options("scripted stop-hook", true, 'P') {
4941 SetHelpLong(
4943 Command Based stop-hooks:
4944 -------------------------
4945 Stop hooks can run a list of lldb commands by providing one or more
4946 --one-line-command options. The commands will get run in the order they are
4947 added. Or you can provide no commands, in which case you will enter a
4948 command editor where you can enter the commands to be run.
4950 Python Based Stop Hooks:
4951 ------------------------
4952 Stop hooks can be implemented with a suitably defined Python class, whose name
4953 is passed in the --python-class option.
4955 When the stop hook is added, the class is initialized by calling:
4957 def __init__(self, target, extra_args, internal_dict):
4959 target: The target that the stop hook is being added to.
4960 extra_args: An SBStructuredData Dictionary filled with the -key -value
4961 option pairs passed to the command.
4962 dict: An implementation detail provided by lldb.
4964 Then when the stop-hook triggers, lldb will run the 'handle_stop' method.
4965 The method has the signature:
4967 def handle_stop(self, exe_ctx, stream):
4969 exe_ctx: An SBExecutionContext for the thread that has stopped.
4970 stream: An SBStream, anything written to this stream will be printed in the
4971 the stop message when the process stops.
4973 Return Value: The method returns "should_stop". If should_stop is false
4974 from all the stop hook executions on threads that stopped
4975 with a reason, then the process will continue. Note that this
4976 will happen only after all the stop hooks are run.
4978 Filter Options:
4979 ---------------
4980 Stop hooks can be set to always run, or to only run when the stopped thread
4981 matches the filter options passed on the command line. The available filter
4982 options include a shared library or a thread or queue specification,
4983 a line range in a source file, a function name or a class name.
4984 )");
4985 m_all_options.Append(&m_python_class_options,
4986 LLDB_OPT_SET_1 | LLDB_OPT_SET_2,
4987 LLDB_OPT_SET_FROM_TO(4, 6));
4988 m_all_options.Append(&m_options);
4989 m_all_options.Finalize();
4992 ~CommandObjectTargetStopHookAdd() override = default;
4994 Options *GetOptions() override { return &m_all_options; }
4996 protected:
4997 void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
4998 StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
4999 if (output_sp && interactive) {
5000 output_sp->PutCString(
5001 "Enter your stop hook command(s). Type 'DONE' to end.\n");
5002 output_sp->Flush();
5006 void IOHandlerInputComplete(IOHandler &io_handler,
5007 std::string &line) override {
5008 if (m_stop_hook_sp) {
5009 if (line.empty()) {
5010 StreamFileSP error_sp(io_handler.GetErrorStreamFileSP());
5011 if (error_sp) {
5012 error_sp->Printf("error: stop hook #%" PRIu64
5013 " aborted, no commands.\n",
5014 m_stop_hook_sp->GetID());
5015 error_sp->Flush();
5017 Target *target = GetDebugger().GetSelectedTarget().get();
5018 if (target) {
5019 target->UndoCreateStopHook(m_stop_hook_sp->GetID());
5021 } else {
5022 // The IOHandler editor is only for command lines stop hooks:
5023 Target::StopHookCommandLine *hook_ptr =
5024 static_cast<Target::StopHookCommandLine *>(m_stop_hook_sp.get());
5026 hook_ptr->SetActionFromString(line);
5027 StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
5028 if (output_sp) {
5029 output_sp->Printf("Stop hook #%" PRIu64 " added.\n",
5030 m_stop_hook_sp->GetID());
5031 output_sp->Flush();
5034 m_stop_hook_sp.reset();
5036 io_handler.SetIsDone(true);
5039 void DoExecute(Args &command, CommandReturnObject &result) override {
5040 m_stop_hook_sp.reset();
5042 Target &target = GetSelectedOrDummyTarget();
5043 Target::StopHookSP new_hook_sp =
5044 target.CreateStopHook(m_python_class_options.GetName().empty() ?
5045 Target::StopHook::StopHookKind::CommandBased
5046 : Target::StopHook::StopHookKind::ScriptBased);
5048 // First step, make the specifier.
5049 std::unique_ptr<SymbolContextSpecifier> specifier_up;
5050 if (m_options.m_sym_ctx_specified) {
5051 specifier_up = std::make_unique<SymbolContextSpecifier>(
5052 GetDebugger().GetSelectedTarget());
5054 if (!m_options.m_module_name.empty()) {
5055 specifier_up->AddSpecification(
5056 m_options.m_module_name.c_str(),
5057 SymbolContextSpecifier::eModuleSpecified);
5060 if (!m_options.m_class_name.empty()) {
5061 specifier_up->AddSpecification(
5062 m_options.m_class_name.c_str(),
5063 SymbolContextSpecifier::eClassOrNamespaceSpecified);
5066 if (!m_options.m_file_name.empty()) {
5067 specifier_up->AddSpecification(m_options.m_file_name.c_str(),
5068 SymbolContextSpecifier::eFileSpecified);
5071 if (m_options.m_line_start != 0) {
5072 specifier_up->AddLineSpecification(
5073 m_options.m_line_start,
5074 SymbolContextSpecifier::eLineStartSpecified);
5077 if (m_options.m_line_end != UINT_MAX) {
5078 specifier_up->AddLineSpecification(
5079 m_options.m_line_end, SymbolContextSpecifier::eLineEndSpecified);
5082 if (!m_options.m_function_name.empty()) {
5083 specifier_up->AddSpecification(
5084 m_options.m_function_name.c_str(),
5085 SymbolContextSpecifier::eFunctionSpecified);
5089 if (specifier_up)
5090 new_hook_sp->SetSpecifier(specifier_up.release());
5092 // Next see if any of the thread options have been entered:
5094 if (m_options.m_thread_specified) {
5095 ThreadSpec *thread_spec = new ThreadSpec();
5097 if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID) {
5098 thread_spec->SetTID(m_options.m_thread_id);
5101 if (m_options.m_thread_index != UINT32_MAX)
5102 thread_spec->SetIndex(m_options.m_thread_index);
5104 if (!m_options.m_thread_name.empty())
5105 thread_spec->SetName(m_options.m_thread_name.c_str());
5107 if (!m_options.m_queue_name.empty())
5108 thread_spec->SetQueueName(m_options.m_queue_name.c_str());
5110 new_hook_sp->SetThreadSpecifier(thread_spec);
5113 new_hook_sp->SetAutoContinue(m_options.m_auto_continue);
5114 if (m_options.m_use_one_liner) {
5115 // This is a command line stop hook:
5116 Target::StopHookCommandLine *hook_ptr =
5117 static_cast<Target::StopHookCommandLine *>(new_hook_sp.get());
5118 hook_ptr->SetActionFromStrings(m_options.m_one_liner);
5119 result.AppendMessageWithFormat("Stop hook #%" PRIu64 " added.\n",
5120 new_hook_sp->GetID());
5121 } else if (!m_python_class_options.GetName().empty()) {
5122 // This is a scripted stop hook:
5123 Target::StopHookScripted *hook_ptr =
5124 static_cast<Target::StopHookScripted *>(new_hook_sp.get());
5125 Status error = hook_ptr->SetScriptCallback(
5126 m_python_class_options.GetName(),
5127 m_python_class_options.GetStructuredData());
5128 if (error.Success())
5129 result.AppendMessageWithFormat("Stop hook #%" PRIu64 " added.\n",
5130 new_hook_sp->GetID());
5131 else {
5132 // FIXME: Set the stop hook ID counter back.
5133 result.AppendErrorWithFormat("Couldn't add stop hook: %s",
5134 error.AsCString());
5135 target.UndoCreateStopHook(new_hook_sp->GetID());
5136 return;
5138 } else {
5139 m_stop_hook_sp = new_hook_sp;
5140 m_interpreter.GetLLDBCommandsFromIOHandler("> ", // Prompt
5141 *this); // IOHandlerDelegate
5143 result.SetStatus(eReturnStatusSuccessFinishNoResult);
5146 private:
5147 CommandOptions m_options;
5148 OptionGroupPythonClassWithDict m_python_class_options;
5149 OptionGroupOptions m_all_options;
5151 Target::StopHookSP m_stop_hook_sp;
5154 #pragma mark CommandObjectTargetStopHookDelete
5156 // CommandObjectTargetStopHookDelete
5158 class CommandObjectTargetStopHookDelete : public CommandObjectParsed {
5159 public:
5160 CommandObjectTargetStopHookDelete(CommandInterpreter &interpreter)
5161 : CommandObjectParsed(interpreter, "target stop-hook delete",
5162 "Delete a stop-hook.",
5163 "target stop-hook delete [<idx>]") {
5164 CommandArgumentData hook_arg{eArgTypeStopHookID, eArgRepeatStar};
5165 m_arguments.push_back({hook_arg});
5168 ~CommandObjectTargetStopHookDelete() override = default;
5170 void
5171 HandleArgumentCompletion(CompletionRequest &request,
5172 OptionElementVector &opt_element_vector) override {
5173 if (request.GetCursorIndex())
5174 return;
5175 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
5176 GetCommandInterpreter(), lldb::eStopHookIDCompletion, request, nullptr);
5179 protected:
5180 void DoExecute(Args &command, CommandReturnObject &result) override {
5181 Target &target = GetSelectedOrDummyTarget();
5182 // FIXME: see if we can use the breakpoint id style parser?
5183 size_t num_args = command.GetArgumentCount();
5184 if (num_args == 0) {
5185 if (!m_interpreter.Confirm("Delete all stop hooks?", true)) {
5186 result.SetStatus(eReturnStatusFailed);
5187 return;
5188 } else {
5189 target.RemoveAllStopHooks();
5191 } else {
5192 for (size_t i = 0; i < num_args; i++) {
5193 lldb::user_id_t user_id;
5194 if (!llvm::to_integer(command.GetArgumentAtIndex(i), user_id)) {
5195 result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n",
5196 command.GetArgumentAtIndex(i));
5197 return;
5199 if (!target.RemoveStopHookByID(user_id)) {
5200 result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n",
5201 command.GetArgumentAtIndex(i));
5202 return;
5206 result.SetStatus(eReturnStatusSuccessFinishNoResult);
5210 #pragma mark CommandObjectTargetStopHookEnableDisable
5212 // CommandObjectTargetStopHookEnableDisable
5214 class CommandObjectTargetStopHookEnableDisable : public CommandObjectParsed {
5215 public:
5216 CommandObjectTargetStopHookEnableDisable(CommandInterpreter &interpreter,
5217 bool enable, const char *name,
5218 const char *help, const char *syntax)
5219 : CommandObjectParsed(interpreter, name, help, syntax), m_enable(enable) {
5220 CommandArgumentData hook_arg{eArgTypeStopHookID, eArgRepeatStar};
5221 m_arguments.push_back({hook_arg});
5224 ~CommandObjectTargetStopHookEnableDisable() override = default;
5226 void
5227 HandleArgumentCompletion(CompletionRequest &request,
5228 OptionElementVector &opt_element_vector) override {
5229 if (request.GetCursorIndex())
5230 return;
5231 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
5232 GetCommandInterpreter(), lldb::eStopHookIDCompletion, request, nullptr);
5235 protected:
5236 void DoExecute(Args &command, CommandReturnObject &result) override {
5237 Target &target = GetSelectedOrDummyTarget();
5238 // FIXME: see if we can use the breakpoint id style parser?
5239 size_t num_args = command.GetArgumentCount();
5240 bool success;
5242 if (num_args == 0) {
5243 target.SetAllStopHooksActiveState(m_enable);
5244 } else {
5245 for (size_t i = 0; i < num_args; i++) {
5246 lldb::user_id_t user_id;
5247 if (!llvm::to_integer(command.GetArgumentAtIndex(i), user_id)) {
5248 result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n",
5249 command.GetArgumentAtIndex(i));
5250 return;
5252 success = target.SetStopHookActiveStateByID(user_id, m_enable);
5253 if (!success) {
5254 result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n",
5255 command.GetArgumentAtIndex(i));
5256 return;
5260 result.SetStatus(eReturnStatusSuccessFinishNoResult);
5263 private:
5264 bool m_enable;
5267 #pragma mark CommandObjectTargetStopHookList
5269 // CommandObjectTargetStopHookList
5271 class CommandObjectTargetStopHookList : public CommandObjectParsed {
5272 public:
5273 CommandObjectTargetStopHookList(CommandInterpreter &interpreter)
5274 : CommandObjectParsed(interpreter, "target stop-hook list",
5275 "List all stop-hooks.", "target stop-hook list") {}
5277 ~CommandObjectTargetStopHookList() override = default;
5279 protected:
5280 void DoExecute(Args &command, CommandReturnObject &result) override {
5281 Target &target = GetSelectedOrDummyTarget();
5283 size_t num_hooks = target.GetNumStopHooks();
5284 if (num_hooks == 0) {
5285 result.GetOutputStream().PutCString("No stop hooks.\n");
5286 } else {
5287 for (size_t i = 0; i < num_hooks; i++) {
5288 Target::StopHookSP this_hook = target.GetStopHookAtIndex(i);
5289 if (i > 0)
5290 result.GetOutputStream().PutCString("\n");
5291 this_hook->GetDescription(result.GetOutputStream(),
5292 eDescriptionLevelFull);
5295 result.SetStatus(eReturnStatusSuccessFinishResult);
5299 #pragma mark CommandObjectMultiwordTargetStopHooks
5301 // CommandObjectMultiwordTargetStopHooks
5303 class CommandObjectMultiwordTargetStopHooks : public CommandObjectMultiword {
5304 public:
5305 CommandObjectMultiwordTargetStopHooks(CommandInterpreter &interpreter)
5306 : CommandObjectMultiword(
5307 interpreter, "target stop-hook",
5308 "Commands for operating on debugger target stop-hooks.",
5309 "target stop-hook <subcommand> [<subcommand-options>]") {
5310 LoadSubCommand("add", CommandObjectSP(
5311 new CommandObjectTargetStopHookAdd(interpreter)));
5312 LoadSubCommand(
5313 "delete",
5314 CommandObjectSP(new CommandObjectTargetStopHookDelete(interpreter)));
5315 LoadSubCommand("disable",
5316 CommandObjectSP(new CommandObjectTargetStopHookEnableDisable(
5317 interpreter, false, "target stop-hook disable [<id>]",
5318 "Disable a stop-hook.", "target stop-hook disable")));
5319 LoadSubCommand("enable",
5320 CommandObjectSP(new CommandObjectTargetStopHookEnableDisable(
5321 interpreter, true, "target stop-hook enable [<id>]",
5322 "Enable a stop-hook.", "target stop-hook enable")));
5323 LoadSubCommand("list", CommandObjectSP(new CommandObjectTargetStopHookList(
5324 interpreter)));
5327 ~CommandObjectMultiwordTargetStopHooks() override = default;
5330 #pragma mark CommandObjectTargetDumpTypesystem
5332 /// Dumps the TypeSystem of the selected Target.
5333 class CommandObjectTargetDumpTypesystem : public CommandObjectParsed {
5334 public:
5335 CommandObjectTargetDumpTypesystem(CommandInterpreter &interpreter)
5336 : CommandObjectParsed(
5337 interpreter, "target dump typesystem",
5338 "Dump the state of the target's internal type system. Intended to "
5339 "be used for debugging LLDB itself.",
5340 nullptr, eCommandRequiresTarget) {}
5342 ~CommandObjectTargetDumpTypesystem() override = default;
5344 protected:
5345 void DoExecute(Args &command, CommandReturnObject &result) override {
5346 // Go over every scratch TypeSystem and dump to the command output.
5347 for (lldb::TypeSystemSP ts : GetSelectedTarget().GetScratchTypeSystems())
5348 if (ts)
5349 ts->Dump(result.GetOutputStream().AsRawOstream());
5351 result.SetStatus(eReturnStatusSuccessFinishResult);
5355 #pragma mark CommandObjectTargetDumpSectionLoadList
5357 /// Dumps the SectionLoadList of the selected Target.
5358 class CommandObjectTargetDumpSectionLoadList : public CommandObjectParsed {
5359 public:
5360 CommandObjectTargetDumpSectionLoadList(CommandInterpreter &interpreter)
5361 : CommandObjectParsed(
5362 interpreter, "target dump section-load-list",
5363 "Dump the state of the target's internal section load list. "
5364 "Intended to be used for debugging LLDB itself.",
5365 nullptr, eCommandRequiresTarget) {}
5367 ~CommandObjectTargetDumpSectionLoadList() override = default;
5369 protected:
5370 void DoExecute(Args &command, CommandReturnObject &result) override {
5371 Target &target = GetSelectedTarget();
5372 target.GetSectionLoadList().Dump(result.GetOutputStream(), &target);
5373 result.SetStatus(eReturnStatusSuccessFinishResult);
5377 #pragma mark CommandObjectTargetDump
5379 /// Multi-word command for 'target dump'.
5380 class CommandObjectTargetDump : public CommandObjectMultiword {
5381 public:
5382 // Constructors and Destructors
5383 CommandObjectTargetDump(CommandInterpreter &interpreter)
5384 : CommandObjectMultiword(
5385 interpreter, "target dump",
5386 "Commands for dumping information about the target.",
5387 "target dump [typesystem|section-load-list]") {
5388 LoadSubCommand(
5389 "typesystem",
5390 CommandObjectSP(new CommandObjectTargetDumpTypesystem(interpreter)));
5391 LoadSubCommand("section-load-list",
5392 CommandObjectSP(new CommandObjectTargetDumpSectionLoadList(
5393 interpreter)));
5396 ~CommandObjectTargetDump() override = default;
5399 #pragma mark CommandObjectMultiwordTarget
5401 // CommandObjectMultiwordTarget
5403 CommandObjectMultiwordTarget::CommandObjectMultiwordTarget(
5404 CommandInterpreter &interpreter)
5405 : CommandObjectMultiword(interpreter, "target",
5406 "Commands for operating on debugger targets.",
5407 "target <subcommand> [<subcommand-options>]") {
5408 LoadSubCommand("create",
5409 CommandObjectSP(new CommandObjectTargetCreate(interpreter)));
5410 LoadSubCommand("delete",
5411 CommandObjectSP(new CommandObjectTargetDelete(interpreter)));
5412 LoadSubCommand("dump",
5413 CommandObjectSP(new CommandObjectTargetDump(interpreter)));
5414 LoadSubCommand("list",
5415 CommandObjectSP(new CommandObjectTargetList(interpreter)));
5416 LoadSubCommand("select",
5417 CommandObjectSP(new CommandObjectTargetSelect(interpreter)));
5418 LoadSubCommand("show-launch-environment",
5419 CommandObjectSP(new CommandObjectTargetShowLaunchEnvironment(
5420 interpreter)));
5421 LoadSubCommand(
5422 "stop-hook",
5423 CommandObjectSP(new CommandObjectMultiwordTargetStopHooks(interpreter)));
5424 LoadSubCommand("modules",
5425 CommandObjectSP(new CommandObjectTargetModules(interpreter)));
5426 LoadSubCommand("symbols",
5427 CommandObjectSP(new CommandObjectTargetSymbols(interpreter)));
5428 LoadSubCommand("variable",
5429 CommandObjectSP(new CommandObjectTargetVariable(interpreter)));
5432 CommandObjectMultiwordTarget::~CommandObjectMultiwordTarget() = default;