[PowerPC] Collect some CallLowering arguments into a struct. [NFC]
[llvm-project.git] / lldb / source / Commands / CommandObjectTarget.cpp
blob8738e850c9f790552bd74b01c8aca86837289d77
1 //===-- CommandObjectTarget.cpp ---------------------------------*- C++ -*-===//
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/Host/StringConvert.h"
20 #include "lldb/Interpreter/CommandInterpreter.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/OptionGroupString.h"
28 #include "lldb/Interpreter/OptionGroupUInt64.h"
29 #include "lldb/Interpreter/OptionGroupUUID.h"
30 #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
31 #include "lldb/Interpreter/OptionGroupVariable.h"
32 #include "lldb/Interpreter/Options.h"
33 #include "lldb/Symbol/CompileUnit.h"
34 #include "lldb/Symbol/FuncUnwinders.h"
35 #include "lldb/Symbol/LineTable.h"
36 #include "lldb/Symbol/LocateSymbolFile.h"
37 #include "lldb/Symbol/ObjectFile.h"
38 #include "lldb/Symbol/SymbolFile.h"
39 #include "lldb/Symbol/UnwindPlan.h"
40 #include "lldb/Symbol/VariableList.h"
41 #include "lldb/Target/ABI.h"
42 #include "lldb/Target/Process.h"
43 #include "lldb/Target/RegisterContext.h"
44 #include "lldb/Target/SectionLoadList.h"
45 #include "lldb/Target/StackFrame.h"
46 #include "lldb/Target/Thread.h"
47 #include "lldb/Target/ThreadSpec.h"
48 #include "lldb/Utility/Args.h"
49 #include "lldb/Utility/State.h"
50 #include "lldb/Utility/Timer.h"
52 #include "llvm/Support/FileSystem.h"
53 #include "llvm/Support/FormatAdapters.h"
56 using namespace lldb;
57 using namespace lldb_private;
59 static void DumpTargetInfo(uint32_t target_idx, Target *target,
60 const char *prefix_cstr,
61 bool show_stopped_process_status, Stream &strm) {
62 const ArchSpec &target_arch = target->GetArchitecture();
64 Module *exe_module = target->GetExecutableModulePointer();
65 char exe_path[PATH_MAX];
66 bool exe_valid = false;
67 if (exe_module)
68 exe_valid = exe_module->GetFileSpec().GetPath(exe_path, sizeof(exe_path));
70 if (!exe_valid)
71 ::strcpy(exe_path, "<none>");
73 strm.Printf("%starget #%u: %s", prefix_cstr ? prefix_cstr : "", target_idx,
74 exe_path);
76 uint32_t properties = 0;
77 if (target_arch.IsValid()) {
78 strm.Printf("%sarch=", properties++ > 0 ? ", " : " ( ");
79 target_arch.DumpTriple(strm.AsRawOstream());
80 properties++;
82 PlatformSP platform_sp(target->GetPlatform());
83 if (platform_sp)
84 strm.Printf("%splatform=%s", properties++ > 0 ? ", " : " ( ",
85 platform_sp->GetName().GetCString());
87 ProcessSP process_sp(target->GetProcessSP());
88 bool show_process_status = false;
89 if (process_sp) {
90 lldb::pid_t pid = process_sp->GetID();
91 StateType state = process_sp->GetState();
92 if (show_stopped_process_status)
93 show_process_status = StateIsStoppedState(state, true);
94 const char *state_cstr = StateAsCString(state);
95 if (pid != LLDB_INVALID_PROCESS_ID)
96 strm.Printf("%spid=%" PRIu64, properties++ > 0 ? ", " : " ( ", pid);
97 strm.Printf("%sstate=%s", properties++ > 0 ? ", " : " ( ", state_cstr);
99 if (properties > 0)
100 strm.PutCString(" )\n");
101 else
102 strm.EOL();
103 if (show_process_status) {
104 const bool only_threads_with_stop_reason = true;
105 const uint32_t start_frame = 0;
106 const uint32_t num_frames = 1;
107 const uint32_t num_frames_with_source = 1;
108 const bool stop_format = false;
109 process_sp->GetStatus(strm);
110 process_sp->GetThreadStatus(strm, only_threads_with_stop_reason,
111 start_frame, num_frames, num_frames_with_source,
112 stop_format);
116 static uint32_t DumpTargetList(TargetList &target_list,
117 bool show_stopped_process_status, Stream &strm) {
118 const uint32_t num_targets = target_list.GetNumTargets();
119 if (num_targets) {
120 TargetSP selected_target_sp(target_list.GetSelectedTarget());
121 strm.PutCString("Current targets:\n");
122 for (uint32_t i = 0; i < num_targets; ++i) {
123 TargetSP target_sp(target_list.GetTargetAtIndex(i));
124 if (target_sp) {
125 bool is_selected = target_sp.get() == selected_target_sp.get();
126 DumpTargetInfo(i, target_sp.get(), is_selected ? "* " : " ",
127 show_stopped_process_status, strm);
131 return num_targets;
134 // Note that the negation in the argument name causes a slightly confusing
135 // mapping of the enum values.
136 static constexpr OptionEnumValueElement g_dependents_enumaration[] = {
138 eLoadDependentsDefault,
139 "default",
140 "Only load dependents when the target is an executable.",
143 eLoadDependentsNo,
144 "true",
145 "Don't load dependents, even if the target is an executable.",
148 eLoadDependentsYes,
149 "false",
150 "Load dependents, even if the target is not an executable.",
154 #define LLDB_OPTIONS_target_dependents
155 #include "CommandOptions.inc"
157 class OptionGroupDependents : public OptionGroup {
158 public:
159 OptionGroupDependents() {}
161 ~OptionGroupDependents() override {}
163 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
164 return llvm::makeArrayRef(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 DISALLOW_COPY_AND_ASSIGN(OptionGroupDependents);
206 #pragma mark CommandObjectTargetCreate
208 // "target create"
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_option_group(), m_arch_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_platform_path(LLDB_OPT_SET_1, false, "platform-path", 'P', 0,
221 eArgTypePath,
222 "Path to the remote file to use for this target."),
223 m_symbol_file(LLDB_OPT_SET_1, false, "symfile", 's', 0,
224 eArgTypeFilename,
225 "Fullpath to a stand alone debug "
226 "symbols file for when debug symbols "
227 "are not in the executable."),
228 m_remote_file(
229 LLDB_OPT_SET_1, false, "remote-file", 'r', 0, eArgTypeFilename,
230 "Fullpath to the file on the remote host if debugging remotely."),
231 m_add_dependents() {
232 CommandArgumentEntry arg;
233 CommandArgumentData file_arg;
235 // Define the first (and only) variant of this arg.
236 file_arg.arg_type = eArgTypeFilename;
237 file_arg.arg_repetition = eArgRepeatPlain;
239 // There is only one variant this argument could be; put it into the
240 // argument entry.
241 arg.push_back(file_arg);
243 // Push the data for the first argument into the m_arguments vector.
244 m_arguments.push_back(arg);
246 m_option_group.Append(&m_arch_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
247 m_option_group.Append(&m_core_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
248 m_option_group.Append(&m_platform_path, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
249 m_option_group.Append(&m_symbol_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
250 m_option_group.Append(&m_remote_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
251 m_option_group.Append(&m_add_dependents, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
252 m_option_group.Finalize();
255 ~CommandObjectTargetCreate() override = default;
257 Options *GetOptions() override { return &m_option_group; }
259 void
260 HandleArgumentCompletion(CompletionRequest &request,
261 OptionElementVector &opt_element_vector) override {
262 CommandCompletions::InvokeCommonCompletionCallbacks(
263 GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
264 request, nullptr);
267 protected:
268 bool DoExecute(Args &command, CommandReturnObject &result) override {
269 const size_t argc = command.GetArgumentCount();
270 FileSpec core_file(m_core_file.GetOptionValue().GetCurrentValue());
271 FileSpec remote_file(m_remote_file.GetOptionValue().GetCurrentValue());
273 if (core_file) {
274 if (!FileSystem::Instance().Exists(core_file)) {
275 result.AppendErrorWithFormat("core file '%s' doesn't exist",
276 core_file.GetPath().c_str());
277 result.SetStatus(eReturnStatusFailed);
278 return false;
280 if (!FileSystem::Instance().Readable(core_file)) {
281 result.AppendErrorWithFormat("core file '%s' is not readable",
282 core_file.GetPath().c_str());
283 result.SetStatus(eReturnStatusFailed);
284 return false;
288 if (argc == 1 || core_file || remote_file) {
289 FileSpec symfile(m_symbol_file.GetOptionValue().GetCurrentValue());
290 if (symfile) {
291 if (FileSystem::Instance().Exists(symfile)) {
292 if (!FileSystem::Instance().Readable(symfile)) {
293 result.AppendErrorWithFormat("symbol file '%s' is not readable",
294 symfile.GetPath().c_str());
295 result.SetStatus(eReturnStatusFailed);
296 return false;
298 } else {
299 char symfile_path[PATH_MAX];
300 symfile.GetPath(symfile_path, sizeof(symfile_path));
301 result.AppendErrorWithFormat("invalid symbol file path '%s'",
302 symfile_path);
303 result.SetStatus(eReturnStatusFailed);
304 return false;
308 const char *file_path = command.GetArgumentAtIndex(0);
309 static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
310 Timer scoped_timer(func_cat, "(lldb) target create '%s'", file_path);
311 FileSpec file_spec;
313 if (file_path) {
314 file_spec.SetFile(file_path, FileSpec::Style::native);
315 FileSystem::Instance().Resolve(file_spec);
318 bool must_set_platform_path = false;
320 Debugger &debugger = GetDebugger();
322 TargetSP target_sp;
323 llvm::StringRef arch_cstr = m_arch_option.GetArchitectureName();
324 Status error(debugger.GetTargetList().CreateTarget(
325 debugger, file_path, arch_cstr,
326 m_add_dependents.m_load_dependent_files, nullptr, target_sp));
328 if (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 if (remote_file) {
336 if (platform_sp) {
337 // I have a remote file.. two possible cases
338 if (file_spec && FileSystem::Instance().Exists(file_spec)) {
339 // if the remote file does not exist, push it there
340 if (!platform_sp->GetFileExists(remote_file)) {
341 Status err = platform_sp->PutFile(file_spec, remote_file);
342 if (err.Fail()) {
343 result.AppendError(err.AsCString());
344 result.SetStatus(eReturnStatusFailed);
345 return false;
348 } else {
349 // there is no local file and we need one
350 // in order to make the remote ---> local transfer we need a
351 // platform
352 // TODO: if the user has passed in a --platform argument, use it
353 // to fetch the right platform
354 if (!platform_sp) {
355 result.AppendError(
356 "unable to perform remote debugging without a platform");
357 result.SetStatus(eReturnStatusFailed);
358 return false;
360 if (file_path) {
361 // copy the remote file to the local file
362 Status err = platform_sp->GetFile(remote_file, file_spec);
363 if (err.Fail()) {
364 result.AppendError(err.AsCString());
365 result.SetStatus(eReturnStatusFailed);
366 return false;
368 } else {
369 // make up a local file
370 result.AppendError("remote --> local transfer without local "
371 "path is not implemented yet");
372 result.SetStatus(eReturnStatusFailed);
373 return false;
376 } else {
377 result.AppendError("no platform found for target");
378 result.SetStatus(eReturnStatusFailed);
379 return false;
383 if (symfile || remote_file) {
384 ModuleSP module_sp(target_sp->GetExecutableModule());
385 if (module_sp) {
386 if (symfile)
387 module_sp->SetSymbolFileFileSpec(symfile);
388 if (remote_file) {
389 std::string remote_path = remote_file.GetPath();
390 target_sp->SetArg0(remote_path.c_str());
391 module_sp->SetPlatformFileSpec(remote_file);
396 debugger.GetTargetList().SetSelectedTarget(target_sp.get());
397 if (must_set_platform_path) {
398 ModuleSpec main_module_spec(file_spec);
399 ModuleSP module_sp =
400 target_sp->GetOrCreateModule(main_module_spec, true /* notify */);
401 if (module_sp)
402 module_sp->SetPlatformFileSpec(remote_file);
404 if (core_file) {
405 char core_path[PATH_MAX];
406 core_file.GetPath(core_path, sizeof(core_path));
407 if (FileSystem::Instance().Exists(core_file)) {
408 if (!FileSystem::Instance().Readable(core_file)) {
409 result.AppendMessageWithFormat(
410 "Core file '%s' is not readable.\n", core_path);
411 result.SetStatus(eReturnStatusFailed);
412 return false;
414 FileSpec core_file_dir;
415 core_file_dir.GetDirectory() = core_file.GetDirectory();
416 target_sp->AppendExecutableSearchPaths(core_file_dir);
418 ProcessSP process_sp(target_sp->CreateProcess(
419 GetDebugger().GetListener(), llvm::StringRef(), &core_file));
421 if (process_sp) {
422 // Seems weird that we Launch a core file, but that is what we
423 // do!
424 error = process_sp->LoadCore();
426 if (error.Fail()) {
427 result.AppendError(
428 error.AsCString("can't find plug-in for core file"));
429 result.SetStatus(eReturnStatusFailed);
430 return false;
431 } else {
432 result.AppendMessageWithFormat(
433 "Core file '%s' (%s) was loaded.\n", core_path,
434 target_sp->GetArchitecture().GetArchitectureName());
435 result.SetStatus(eReturnStatusSuccessFinishNoResult);
437 } else {
438 result.AppendErrorWithFormat(
439 "Unable to find process plug-in for core file '%s'\n",
440 core_path);
441 result.SetStatus(eReturnStatusFailed);
443 } else {
444 result.AppendErrorWithFormat("Core file '%s' does not exist\n",
445 core_path);
446 result.SetStatus(eReturnStatusFailed);
448 } else {
449 result.AppendMessageWithFormat(
450 "Current executable set to '%s' (%s).\n",
451 file_spec.GetPath().c_str(),
452 target_sp->GetArchitecture().GetArchitectureName());
453 result.SetStatus(eReturnStatusSuccessFinishNoResult);
455 } else {
456 result.AppendError(error.AsCString());
457 result.SetStatus(eReturnStatusFailed);
459 } else {
460 result.AppendErrorWithFormat("'%s' takes exactly one executable path "
461 "argument, or use the --core option.\n",
462 m_cmd_name.c_str());
463 result.SetStatus(eReturnStatusFailed);
465 return result.Succeeded();
468 private:
469 OptionGroupOptions m_option_group;
470 OptionGroupArchitecture m_arch_option;
471 OptionGroupFile m_core_file;
472 OptionGroupFile m_platform_path;
473 OptionGroupFile m_symbol_file;
474 OptionGroupFile m_remote_file;
475 OptionGroupDependents m_add_dependents;
478 #pragma mark CommandObjectTargetList
480 // "target list"
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 bool DoExecute(Args &args, CommandReturnObject &result) override {
494 if (args.GetArgumentCount() == 0) {
495 Stream &strm = result.GetOutputStream();
497 bool show_stopped_process_status = false;
498 if (DumpTargetList(GetDebugger().GetTargetList(),
499 show_stopped_process_status, strm) == 0) {
500 strm.PutCString("No targets.\n");
502 result.SetStatus(eReturnStatusSuccessFinishResult);
503 } else {
504 result.AppendError("the 'target list' command takes no arguments\n");
505 result.SetStatus(eReturnStatusFailed);
507 return result.Succeeded();
511 #pragma mark CommandObjectTargetSelect
513 // "target select"
515 class CommandObjectTargetSelect : public CommandObjectParsed {
516 public:
517 CommandObjectTargetSelect(CommandInterpreter &interpreter)
518 : CommandObjectParsed(
519 interpreter, "target select",
520 "Select a target as the current target by target index.", nullptr) {
523 ~CommandObjectTargetSelect() override = default;
525 protected:
526 bool DoExecute(Args &args, CommandReturnObject &result) override {
527 if (args.GetArgumentCount() == 1) {
528 bool success = false;
529 const char *target_idx_arg = args.GetArgumentAtIndex(0);
530 uint32_t target_idx =
531 StringConvert::ToUInt32(target_idx_arg, UINT32_MAX, 0, &success);
532 if (success) {
533 TargetList &target_list = GetDebugger().GetTargetList();
534 const uint32_t num_targets = target_list.GetNumTargets();
535 if (target_idx < num_targets) {
536 TargetSP target_sp(target_list.GetTargetAtIndex(target_idx));
537 if (target_sp) {
538 Stream &strm = result.GetOutputStream();
539 target_list.SetSelectedTarget(target_sp.get());
540 bool show_stopped_process_status = false;
541 DumpTargetList(target_list, show_stopped_process_status, strm);
542 result.SetStatus(eReturnStatusSuccessFinishResult);
543 } else {
544 result.AppendErrorWithFormat("target #%u is NULL in target list\n",
545 target_idx);
546 result.SetStatus(eReturnStatusFailed);
548 } else {
549 if (num_targets > 0) {
550 result.AppendErrorWithFormat(
551 "index %u is out of range, valid target indexes are 0 - %u\n",
552 target_idx, num_targets - 1);
553 } else {
554 result.AppendErrorWithFormat(
555 "index %u is out of range since there are no active targets\n",
556 target_idx);
558 result.SetStatus(eReturnStatusFailed);
560 } else {
561 result.AppendErrorWithFormat("invalid index string value '%s'\n",
562 target_idx_arg);
563 result.SetStatus(eReturnStatusFailed);
565 } else {
566 result.AppendError(
567 "'target select' takes a single argument: a target index\n");
568 result.SetStatus(eReturnStatusFailed);
570 return result.Succeeded();
574 #pragma mark CommandObjectTargetSelect
576 // "target delete"
578 class CommandObjectTargetDelete : public CommandObjectParsed {
579 public:
580 CommandObjectTargetDelete(CommandInterpreter &interpreter)
581 : CommandObjectParsed(interpreter, "target delete",
582 "Delete one or more targets by target index.",
583 nullptr),
584 m_option_group(), m_all_option(LLDB_OPT_SET_1, false, "all", 'a',
585 "Delete all targets.", false, true),
586 m_cleanup_option(
587 LLDB_OPT_SET_1, false, "clean", 'c',
588 "Perform extra cleanup to minimize memory consumption after "
589 "deleting the target. "
590 "By default, LLDB will keep in memory any modules previously "
591 "loaded by the target as well "
592 "as all of its debug info. Specifying --clean will unload all of "
593 "these shared modules and "
594 "cause them to be reparsed again the next time the target is run",
595 false, true) {
596 m_option_group.Append(&m_all_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
597 m_option_group.Append(&m_cleanup_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
598 m_option_group.Finalize();
601 ~CommandObjectTargetDelete() override = default;
603 Options *GetOptions() override { return &m_option_group; }
605 protected:
606 bool DoExecute(Args &args, CommandReturnObject &result) override {
607 const size_t argc = args.GetArgumentCount();
608 std::vector<TargetSP> delete_target_list;
609 TargetList &target_list = GetDebugger().GetTargetList();
610 TargetSP target_sp;
612 if (m_all_option.GetOptionValue()) {
613 for (int i = 0; i < target_list.GetNumTargets(); ++i)
614 delete_target_list.push_back(target_list.GetTargetAtIndex(i));
615 } else if (argc > 0) {
616 const uint32_t num_targets = target_list.GetNumTargets();
617 // Bail out if don't have any targets.
618 if (num_targets == 0) {
619 result.AppendError("no targets to delete");
620 result.SetStatus(eReturnStatusFailed);
621 return false;
624 for (auto &entry : args.entries()) {
625 uint32_t target_idx;
626 if (entry.ref().getAsInteger(0, target_idx)) {
627 result.AppendErrorWithFormat("invalid target index '%s'\n",
628 entry.c_str());
629 result.SetStatus(eReturnStatusFailed);
630 return false;
632 if (target_idx < num_targets) {
633 target_sp = target_list.GetTargetAtIndex(target_idx);
634 if (target_sp) {
635 delete_target_list.push_back(target_sp);
636 continue;
639 if (num_targets > 1)
640 result.AppendErrorWithFormat("target index %u is out of range, valid "
641 "target indexes are 0 - %u\n",
642 target_idx, num_targets - 1);
643 else
644 result.AppendErrorWithFormat(
645 "target index %u is out of range, the only valid index is 0\n",
646 target_idx);
648 result.SetStatus(eReturnStatusFailed);
649 return false;
651 } else {
652 target_sp = target_list.GetSelectedTarget();
653 if (!target_sp) {
654 result.AppendErrorWithFormat("no target is currently selected\n");
655 result.SetStatus(eReturnStatusFailed);
656 return false;
658 delete_target_list.push_back(target_sp);
661 const size_t num_targets_to_delete = delete_target_list.size();
662 for (size_t idx = 0; idx < num_targets_to_delete; ++idx) {
663 target_sp = delete_target_list[idx];
664 target_list.DeleteTarget(target_sp);
665 target_sp->Destroy();
667 // If "--clean" was specified, prune any orphaned shared modules from the
668 // global shared module list
669 if (m_cleanup_option.GetOptionValue()) {
670 const bool mandatory = true;
671 ModuleList::RemoveOrphanSharedModules(mandatory);
673 result.GetOutputStream().Printf("%u targets deleted.\n",
674 (uint32_t)num_targets_to_delete);
675 result.SetStatus(eReturnStatusSuccessFinishResult);
677 return true;
680 OptionGroupOptions m_option_group;
681 OptionGroupBoolean m_all_option;
682 OptionGroupBoolean m_cleanup_option;
685 #pragma mark CommandObjectTargetVariable
687 // "target variable"
689 class CommandObjectTargetVariable : public CommandObjectParsed {
690 static const uint32_t SHORT_OPTION_FILE = 0x66696c65; // 'file'
691 static const uint32_t SHORT_OPTION_SHLB = 0x73686c62; // 'shlb'
693 public:
694 CommandObjectTargetVariable(CommandInterpreter &interpreter)
695 : CommandObjectParsed(interpreter, "target variable",
696 "Read global variables for the current target, "
697 "before or while running a process.",
698 nullptr, eCommandRequiresTarget),
699 m_option_group(),
700 m_option_variable(false), // Don't include frame options
701 m_option_format(eFormatDefault),
702 m_option_compile_units(LLDB_OPT_SET_1, false, "file", SHORT_OPTION_FILE,
703 0, eArgTypeFilename,
704 "A basename or fullpath to a file that contains "
705 "global variables. This option can be "
706 "specified multiple times."),
707 m_option_shared_libraries(
708 LLDB_OPT_SET_1, false, "shlib", SHORT_OPTION_SHLB, 0,
709 eArgTypeFilename,
710 "A basename or fullpath to a shared library to use in the search "
711 "for global "
712 "variables. This option can be specified multiple times."),
713 m_varobj_options() {
714 CommandArgumentEntry arg;
715 CommandArgumentData var_name_arg;
717 // Define the first (and only) variant of this arg.
718 var_name_arg.arg_type = eArgTypeVarName;
719 var_name_arg.arg_repetition = eArgRepeatPlus;
721 // There is only one variant this argument could be; put it into the
722 // argument entry.
723 arg.push_back(var_name_arg);
725 // Push the data for the first argument into the m_arguments vector.
726 m_arguments.push_back(arg);
728 m_option_group.Append(&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
729 m_option_group.Append(&m_option_variable, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
730 m_option_group.Append(&m_option_format,
731 OptionGroupFormat::OPTION_GROUP_FORMAT |
732 OptionGroupFormat::OPTION_GROUP_GDB_FMT,
733 LLDB_OPT_SET_1);
734 m_option_group.Append(&m_option_compile_units, LLDB_OPT_SET_ALL,
735 LLDB_OPT_SET_1);
736 m_option_group.Append(&m_option_shared_libraries, LLDB_OPT_SET_ALL,
737 LLDB_OPT_SET_1);
738 m_option_group.Finalize();
741 ~CommandObjectTargetVariable() override = default;
743 void DumpValueObject(Stream &s, VariableSP &var_sp, ValueObjectSP &valobj_sp,
744 const char *root_name) {
745 DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions());
747 if (!valobj_sp->GetTargetSP()->GetDisplayRuntimeSupportValues() &&
748 valobj_sp->IsRuntimeSupportValue())
749 return;
751 switch (var_sp->GetScope()) {
752 case eValueTypeVariableGlobal:
753 if (m_option_variable.show_scope)
754 s.PutCString("GLOBAL: ");
755 break;
757 case eValueTypeVariableStatic:
758 if (m_option_variable.show_scope)
759 s.PutCString("STATIC: ");
760 break;
762 case eValueTypeVariableArgument:
763 if (m_option_variable.show_scope)
764 s.PutCString(" ARG: ");
765 break;
767 case eValueTypeVariableLocal:
768 if (m_option_variable.show_scope)
769 s.PutCString(" LOCAL: ");
770 break;
772 case eValueTypeVariableThreadLocal:
773 if (m_option_variable.show_scope)
774 s.PutCString("THREAD: ");
775 break;
777 default:
778 break;
781 if (m_option_variable.show_decl) {
782 bool show_fullpaths = false;
783 bool show_module = true;
784 if (var_sp->DumpDeclaration(&s, show_fullpaths, show_module))
785 s.PutCString(": ");
788 const Format format = m_option_format.GetFormat();
789 if (format != eFormatDefault)
790 options.SetFormat(format);
792 options.SetRootValueObjectName(root_name);
794 valobj_sp->Dump(s, options);
797 static size_t GetVariableCallback(void *baton, const char *name,
798 VariableList &variable_list) {
799 size_t old_size = variable_list.GetSize();
800 Target *target = static_cast<Target *>(baton);
801 if (target)
802 target->GetImages().FindGlobalVariables(ConstString(name), UINT32_MAX,
803 variable_list);
804 return variable_list.GetSize() - old_size;
807 Options *GetOptions() override { return &m_option_group; }
809 protected:
810 void DumpGlobalVariableList(const ExecutionContext &exe_ctx,
811 const SymbolContext &sc,
812 const VariableList &variable_list, Stream &s) {
813 if (variable_list.Empty())
814 return;
815 if (sc.module_sp) {
816 if (sc.comp_unit) {
817 s.Format("Global variables for {0} in {1}:\n",
818 sc.comp_unit->GetPrimaryFile(), sc.module_sp->GetFileSpec());
819 } else {
820 s.Printf("Global variables for %s\n",
821 sc.module_sp->GetFileSpec().GetPath().c_str());
823 } else if (sc.comp_unit) {
824 s.Format("Global variables for {0}\n", sc.comp_unit->GetPrimaryFile());
827 for (VariableSP var_sp : variable_list) {
828 if (!var_sp)
829 continue;
830 ValueObjectSP valobj_sp(ValueObjectVariable::Create(
831 exe_ctx.GetBestExecutionContextScope(), var_sp));
833 if (valobj_sp)
834 DumpValueObject(s, var_sp, valobj_sp, var_sp->GetName().GetCString());
838 bool DoExecute(Args &args, CommandReturnObject &result) override {
839 Target *target = m_exe_ctx.GetTargetPtr();
840 const size_t argc = args.GetArgumentCount();
841 Stream &s = result.GetOutputStream();
843 if (argc > 0) {
845 // TODO: Convert to entry-based iteration. Requires converting
846 // DumpValueObject.
847 for (size_t idx = 0; idx < argc; ++idx) {
848 VariableList variable_list;
849 ValueObjectList valobj_list;
851 const char *arg = args.GetArgumentAtIndex(idx);
852 size_t matches = 0;
853 bool use_var_name = false;
854 if (m_option_variable.use_regex) {
855 RegularExpression regex(llvm::StringRef::withNullAsEmpty(arg));
856 if (!regex.IsValid()) {
857 result.GetErrorStream().Printf(
858 "error: invalid regular expression: '%s'\n", arg);
859 result.SetStatus(eReturnStatusFailed);
860 return false;
862 use_var_name = true;
863 target->GetImages().FindGlobalVariables(regex, UINT32_MAX,
864 variable_list);
865 matches = variable_list.GetSize();
866 } else {
867 Status error(Variable::GetValuesForVariableExpressionPath(
868 arg, m_exe_ctx.GetBestExecutionContextScope(),
869 GetVariableCallback, target, variable_list, valobj_list));
870 matches = variable_list.GetSize();
873 if (matches == 0) {
874 result.GetErrorStream().Printf(
875 "error: can't find global variable '%s'\n", arg);
876 result.SetStatus(eReturnStatusFailed);
877 return false;
878 } else {
879 for (uint32_t global_idx = 0; global_idx < matches; ++global_idx) {
880 VariableSP var_sp(variable_list.GetVariableAtIndex(global_idx));
881 if (var_sp) {
882 ValueObjectSP valobj_sp(
883 valobj_list.GetValueObjectAtIndex(global_idx));
884 if (!valobj_sp)
885 valobj_sp = ValueObjectVariable::Create(
886 m_exe_ctx.GetBestExecutionContextScope(), var_sp);
888 if (valobj_sp)
889 DumpValueObject(s, var_sp, valobj_sp,
890 use_var_name ? var_sp->GetName().GetCString()
891 : arg);
896 } else {
897 const FileSpecList &compile_units =
898 m_option_compile_units.GetOptionValue().GetCurrentValue();
899 const FileSpecList &shlibs =
900 m_option_shared_libraries.GetOptionValue().GetCurrentValue();
901 SymbolContextList sc_list;
902 const size_t num_compile_units = compile_units.GetSize();
903 const size_t num_shlibs = shlibs.GetSize();
904 if (num_compile_units == 0 && num_shlibs == 0) {
905 bool success = false;
906 StackFrame *frame = m_exe_ctx.GetFramePtr();
907 CompileUnit *comp_unit = nullptr;
908 if (frame) {
909 SymbolContext sc = frame->GetSymbolContext(eSymbolContextCompUnit);
910 if (sc.comp_unit) {
911 const bool can_create = true;
912 VariableListSP comp_unit_varlist_sp(
913 sc.comp_unit->GetVariableList(can_create));
914 if (comp_unit_varlist_sp) {
915 size_t count = comp_unit_varlist_sp->GetSize();
916 if (count > 0) {
917 DumpGlobalVariableList(m_exe_ctx, sc, *comp_unit_varlist_sp, s);
918 success = true;
923 if (!success) {
924 if (frame) {
925 if (comp_unit)
926 result.AppendErrorWithFormatv(
927 "no global variables in current compile unit: {0}\n",
928 comp_unit->GetPrimaryFile());
929 else
930 result.AppendErrorWithFormat(
931 "no debug information for frame %u\n",
932 frame->GetFrameIndex());
933 } else
934 result.AppendError("'target variable' takes one or more global "
935 "variable names as arguments\n");
936 result.SetStatus(eReturnStatusFailed);
938 } else {
939 SymbolContextList sc_list;
940 // We have one or more compile unit or shlib
941 if (num_shlibs > 0) {
942 for (size_t shlib_idx = 0; shlib_idx < num_shlibs; ++shlib_idx) {
943 const FileSpec module_file(shlibs.GetFileSpecAtIndex(shlib_idx));
944 ModuleSpec module_spec(module_file);
946 ModuleSP module_sp(
947 target->GetImages().FindFirstModule(module_spec));
948 if (module_sp) {
949 if (num_compile_units > 0) {
950 for (size_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
951 module_sp->FindCompileUnits(
952 compile_units.GetFileSpecAtIndex(cu_idx), sc_list);
953 } else {
954 SymbolContext sc;
955 sc.module_sp = module_sp;
956 sc_list.Append(sc);
958 } else {
959 // Didn't find matching shlib/module in target...
960 result.AppendErrorWithFormat(
961 "target doesn't contain the specified shared library: %s\n",
962 module_file.GetPath().c_str());
965 } else {
966 // No shared libraries, we just want to find globals for the compile
967 // units files that were specified
968 for (size_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
969 target->GetImages().FindCompileUnits(
970 compile_units.GetFileSpecAtIndex(cu_idx), sc_list);
973 const uint32_t num_scs = sc_list.GetSize();
974 if (num_scs > 0) {
975 SymbolContext sc;
976 for (uint32_t sc_idx = 0; sc_idx < num_scs; ++sc_idx) {
977 if (sc_list.GetContextAtIndex(sc_idx, sc)) {
978 if (sc.comp_unit) {
979 const bool can_create = true;
980 VariableListSP comp_unit_varlist_sp(
981 sc.comp_unit->GetVariableList(can_create));
982 if (comp_unit_varlist_sp)
983 DumpGlobalVariableList(m_exe_ctx, sc, *comp_unit_varlist_sp,
985 } else if (sc.module_sp) {
986 // Get all global variables for this module
987 lldb_private::RegularExpression all_globals_regex(
988 llvm::StringRef(
989 ".")); // Any global with at least one character
990 VariableList variable_list;
991 sc.module_sp->FindGlobalVariables(all_globals_regex, UINT32_MAX,
992 variable_list);
993 DumpGlobalVariableList(m_exe_ctx, sc, variable_list, s);
1001 if (m_interpreter.TruncationWarningNecessary()) {
1002 result.GetOutputStream().Printf(m_interpreter.TruncationWarningText(),
1003 m_cmd_name.c_str());
1004 m_interpreter.TruncationWarningGiven();
1007 return result.Succeeded();
1010 OptionGroupOptions m_option_group;
1011 OptionGroupVariable m_option_variable;
1012 OptionGroupFormat m_option_format;
1013 OptionGroupFileList m_option_compile_units;
1014 OptionGroupFileList m_option_shared_libraries;
1015 OptionGroupValueObjectDisplay m_varobj_options;
1018 #pragma mark CommandObjectTargetModulesSearchPathsAdd
1020 class CommandObjectTargetModulesSearchPathsAdd : public CommandObjectParsed {
1021 public:
1022 CommandObjectTargetModulesSearchPathsAdd(CommandInterpreter &interpreter)
1023 : CommandObjectParsed(interpreter, "target modules search-paths add",
1024 "Add new image search paths substitution pairs to "
1025 "the current target.",
1026 nullptr, eCommandRequiresTarget) {
1027 CommandArgumentEntry arg;
1028 CommandArgumentData old_prefix_arg;
1029 CommandArgumentData new_prefix_arg;
1031 // Define the first variant of this arg pair.
1032 old_prefix_arg.arg_type = eArgTypeOldPathPrefix;
1033 old_prefix_arg.arg_repetition = eArgRepeatPairPlus;
1035 // Define the first variant of this arg pair.
1036 new_prefix_arg.arg_type = eArgTypeNewPathPrefix;
1037 new_prefix_arg.arg_repetition = eArgRepeatPairPlus;
1039 // There are two required arguments that must always occur together, i.e.
1040 // an argument "pair". Because they must always occur together, they are
1041 // treated as two variants of one argument rather than two independent
1042 // arguments. Push them both into the first argument position for
1043 // m_arguments...
1045 arg.push_back(old_prefix_arg);
1046 arg.push_back(new_prefix_arg);
1048 m_arguments.push_back(arg);
1051 ~CommandObjectTargetModulesSearchPathsAdd() override = default;
1053 protected:
1054 bool DoExecute(Args &command, CommandReturnObject &result) override {
1055 Target *target = &GetSelectedTarget();
1056 const size_t argc = command.GetArgumentCount();
1057 if (argc & 1) {
1058 result.AppendError("add requires an even number of arguments\n");
1059 result.SetStatus(eReturnStatusFailed);
1060 } else {
1061 for (size_t i = 0; i < argc; i += 2) {
1062 const char *from = command.GetArgumentAtIndex(i);
1063 const char *to = command.GetArgumentAtIndex(i + 1);
1065 if (from[0] && to[0]) {
1066 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
1067 if (log) {
1068 LLDB_LOGF(log,
1069 "target modules search path adding ImageSearchPath "
1070 "pair: '%s' -> '%s'",
1071 from, to);
1073 bool last_pair = ((argc - i) == 2);
1074 target->GetImageSearchPathList().Append(
1075 ConstString(from), ConstString(to),
1076 last_pair); // Notify if this is the last pair
1077 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1078 } else {
1079 if (from[0])
1080 result.AppendError("<path-prefix> can't be empty\n");
1081 else
1082 result.AppendError("<new-path-prefix> can't be empty\n");
1083 result.SetStatus(eReturnStatusFailed);
1087 return result.Succeeded();
1091 #pragma mark CommandObjectTargetModulesSearchPathsClear
1093 class CommandObjectTargetModulesSearchPathsClear : public CommandObjectParsed {
1094 public:
1095 CommandObjectTargetModulesSearchPathsClear(CommandInterpreter &interpreter)
1096 : CommandObjectParsed(interpreter, "target modules search-paths clear",
1097 "Clear all current image search path substitution "
1098 "pairs from the current target.",
1099 "target modules search-paths clear",
1100 eCommandRequiresTarget) {}
1102 ~CommandObjectTargetModulesSearchPathsClear() override = default;
1104 protected:
1105 bool DoExecute(Args &command, CommandReturnObject &result) override {
1106 Target *target = &GetSelectedTarget();
1107 bool notify = true;
1108 target->GetImageSearchPathList().Clear(notify);
1109 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1110 return result.Succeeded();
1114 #pragma mark CommandObjectTargetModulesSearchPathsInsert
1116 class CommandObjectTargetModulesSearchPathsInsert : public CommandObjectParsed {
1117 public:
1118 CommandObjectTargetModulesSearchPathsInsert(CommandInterpreter &interpreter)
1119 : CommandObjectParsed(interpreter, "target modules search-paths insert",
1120 "Insert a new image search path substitution pair "
1121 "into the current target at the specified index.",
1122 nullptr, eCommandRequiresTarget) {
1123 CommandArgumentEntry arg1;
1124 CommandArgumentEntry arg2;
1125 CommandArgumentData index_arg;
1126 CommandArgumentData old_prefix_arg;
1127 CommandArgumentData new_prefix_arg;
1129 // Define the first and only variant of this arg.
1130 index_arg.arg_type = eArgTypeIndex;
1131 index_arg.arg_repetition = eArgRepeatPlain;
1133 // Put the one and only variant into the first arg for m_arguments:
1134 arg1.push_back(index_arg);
1136 // Define the first variant of this arg pair.
1137 old_prefix_arg.arg_type = eArgTypeOldPathPrefix;
1138 old_prefix_arg.arg_repetition = eArgRepeatPairPlus;
1140 // Define the first variant of this arg pair.
1141 new_prefix_arg.arg_type = eArgTypeNewPathPrefix;
1142 new_prefix_arg.arg_repetition = eArgRepeatPairPlus;
1144 // There are two required arguments that must always occur together, i.e.
1145 // an argument "pair". Because they must always occur together, they are
1146 // treated as two variants of one argument rather than two independent
1147 // arguments. Push them both into the same argument position for
1148 // m_arguments...
1150 arg2.push_back(old_prefix_arg);
1151 arg2.push_back(new_prefix_arg);
1153 // Add arguments to m_arguments.
1154 m_arguments.push_back(arg1);
1155 m_arguments.push_back(arg2);
1158 ~CommandObjectTargetModulesSearchPathsInsert() override = default;
1160 protected:
1161 bool DoExecute(Args &command, CommandReturnObject &result) override {
1162 Target *target = &GetSelectedTarget();
1163 size_t argc = command.GetArgumentCount();
1164 // check for at least 3 arguments and an odd number of parameters
1165 if (argc >= 3 && argc & 1) {
1166 bool success = false;
1168 uint32_t insert_idx = StringConvert::ToUInt32(
1169 command.GetArgumentAtIndex(0), UINT32_MAX, 0, &success);
1171 if (!success) {
1172 result.AppendErrorWithFormat(
1173 "<index> parameter is not an integer: '%s'.\n",
1174 command.GetArgumentAtIndex(0));
1175 result.SetStatus(eReturnStatusFailed);
1176 return result.Succeeded();
1179 // shift off the index
1180 command.Shift();
1181 argc = command.GetArgumentCount();
1183 for (uint32_t i = 0; i < argc; i += 2, ++insert_idx) {
1184 const char *from = command.GetArgumentAtIndex(i);
1185 const char *to = command.GetArgumentAtIndex(i + 1);
1187 if (from[0] && to[0]) {
1188 bool last_pair = ((argc - i) == 2);
1189 target->GetImageSearchPathList().Insert(
1190 ConstString(from), ConstString(to), insert_idx, last_pair);
1191 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1192 } else {
1193 if (from[0])
1194 result.AppendError("<path-prefix> can't be empty\n");
1195 else
1196 result.AppendError("<new-path-prefix> can't be empty\n");
1197 result.SetStatus(eReturnStatusFailed);
1198 return false;
1201 } else {
1202 result.AppendError("insert requires at least three arguments\n");
1203 result.SetStatus(eReturnStatusFailed);
1204 return result.Succeeded();
1206 return result.Succeeded();
1210 #pragma mark CommandObjectTargetModulesSearchPathsList
1212 class CommandObjectTargetModulesSearchPathsList : public CommandObjectParsed {
1213 public:
1214 CommandObjectTargetModulesSearchPathsList(CommandInterpreter &interpreter)
1215 : CommandObjectParsed(interpreter, "target modules search-paths list",
1216 "List all current image search path substitution "
1217 "pairs in the current target.",
1218 "target modules search-paths list",
1219 eCommandRequiresTarget) {}
1221 ~CommandObjectTargetModulesSearchPathsList() override = default;
1223 protected:
1224 bool DoExecute(Args &command, CommandReturnObject &result) override {
1225 Target *target = &GetSelectedTarget();
1226 if (command.GetArgumentCount() != 0) {
1227 result.AppendError("list takes no arguments\n");
1228 result.SetStatus(eReturnStatusFailed);
1229 return result.Succeeded();
1232 target->GetImageSearchPathList().Dump(&result.GetOutputStream());
1233 result.SetStatus(eReturnStatusSuccessFinishResult);
1234 return result.Succeeded();
1238 #pragma mark CommandObjectTargetModulesSearchPathsQuery
1240 class CommandObjectTargetModulesSearchPathsQuery : public CommandObjectParsed {
1241 public:
1242 CommandObjectTargetModulesSearchPathsQuery(CommandInterpreter &interpreter)
1243 : CommandObjectParsed(
1244 interpreter, "target modules search-paths query",
1245 "Transform a path using the first applicable image search path.",
1246 nullptr, eCommandRequiresTarget) {
1247 CommandArgumentEntry arg;
1248 CommandArgumentData path_arg;
1250 // Define the first (and only) variant of this arg.
1251 path_arg.arg_type = eArgTypeDirectoryName;
1252 path_arg.arg_repetition = eArgRepeatPlain;
1254 // There is only one variant this argument could be; put it into the
1255 // argument entry.
1256 arg.push_back(path_arg);
1258 // Push the data for the first argument into the m_arguments vector.
1259 m_arguments.push_back(arg);
1262 ~CommandObjectTargetModulesSearchPathsQuery() override = default;
1264 protected:
1265 bool DoExecute(Args &command, CommandReturnObject &result) override {
1266 Target *target = &GetSelectedTarget();
1267 if (command.GetArgumentCount() != 1) {
1268 result.AppendError("query requires one argument\n");
1269 result.SetStatus(eReturnStatusFailed);
1270 return result.Succeeded();
1273 ConstString orig(command.GetArgumentAtIndex(0));
1274 ConstString transformed;
1275 if (target->GetImageSearchPathList().RemapPath(orig, transformed))
1276 result.GetOutputStream().Printf("%s\n", transformed.GetCString());
1277 else
1278 result.GetOutputStream().Printf("%s\n", orig.GetCString());
1280 result.SetStatus(eReturnStatusSuccessFinishResult);
1281 return result.Succeeded();
1285 // Static Helper functions
1286 static void DumpModuleArchitecture(Stream &strm, Module *module,
1287 bool full_triple, uint32_t width) {
1288 if (module) {
1289 StreamString arch_strm;
1291 if (full_triple)
1292 module->GetArchitecture().DumpTriple(arch_strm.AsRawOstream());
1293 else
1294 arch_strm.PutCString(module->GetArchitecture().GetArchitectureName());
1295 std::string arch_str = arch_strm.GetString();
1297 if (width)
1298 strm.Printf("%-*s", width, arch_str.c_str());
1299 else
1300 strm.PutCString(arch_str);
1304 static void DumpModuleUUID(Stream &strm, Module *module) {
1305 if (module && module->GetUUID().IsValid())
1306 module->GetUUID().Dump(&strm);
1307 else
1308 strm.PutCString(" ");
1311 static uint32_t DumpCompileUnitLineTable(CommandInterpreter &interpreter,
1312 Stream &strm, Module *module,
1313 const FileSpec &file_spec,
1314 lldb::DescriptionLevel desc_level) {
1315 uint32_t num_matches = 0;
1316 if (module) {
1317 SymbolContextList sc_list;
1318 num_matches = module->ResolveSymbolContextsForFileSpec(
1319 file_spec, 0, false, eSymbolContextCompUnit, sc_list);
1321 for (uint32_t i = 0; i < num_matches; ++i) {
1322 SymbolContext sc;
1323 if (sc_list.GetContextAtIndex(i, sc)) {
1324 if (i > 0)
1325 strm << "\n\n";
1327 strm << "Line table for " << sc.comp_unit->GetPrimaryFile() << " in `"
1328 << module->GetFileSpec().GetFilename() << "\n";
1329 LineTable *line_table = sc.comp_unit->GetLineTable();
1330 if (line_table)
1331 line_table->GetDescription(
1332 &strm, interpreter.GetExecutionContext().GetTargetPtr(),
1333 desc_level);
1334 else
1335 strm << "No line table";
1339 return num_matches;
1342 static void DumpFullpath(Stream &strm, const FileSpec *file_spec_ptr,
1343 uint32_t width) {
1344 if (file_spec_ptr) {
1345 if (width > 0) {
1346 std::string fullpath = file_spec_ptr->GetPath();
1347 strm.Printf("%-*s", width, fullpath.c_str());
1348 return;
1349 } else {
1350 file_spec_ptr->Dump(strm.AsRawOstream());
1351 return;
1354 // Keep the width spacing correct if things go wrong...
1355 if (width > 0)
1356 strm.Printf("%-*s", width, "");
1359 static void DumpDirectory(Stream &strm, const FileSpec *file_spec_ptr,
1360 uint32_t width) {
1361 if (file_spec_ptr) {
1362 if (width > 0)
1363 strm.Printf("%-*s", width, file_spec_ptr->GetDirectory().AsCString(""));
1364 else
1365 file_spec_ptr->GetDirectory().Dump(&strm);
1366 return;
1368 // Keep the width spacing correct if things go wrong...
1369 if (width > 0)
1370 strm.Printf("%-*s", width, "");
1373 static void DumpBasename(Stream &strm, const FileSpec *file_spec_ptr,
1374 uint32_t width) {
1375 if (file_spec_ptr) {
1376 if (width > 0)
1377 strm.Printf("%-*s", width, file_spec_ptr->GetFilename().AsCString(""));
1378 else
1379 file_spec_ptr->GetFilename().Dump(&strm);
1380 return;
1382 // Keep the width spacing correct if things go wrong...
1383 if (width > 0)
1384 strm.Printf("%-*s", width, "");
1387 static size_t DumpModuleObjfileHeaders(Stream &strm, ModuleList &module_list) {
1388 size_t num_dumped = 0;
1389 std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex());
1390 const size_t num_modules = module_list.GetSize();
1391 if (num_modules > 0) {
1392 strm.Printf("Dumping headers for %" PRIu64 " module(s).\n",
1393 static_cast<uint64_t>(num_modules));
1394 strm.IndentMore();
1395 for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
1396 Module *module = module_list.GetModulePointerAtIndexUnlocked(image_idx);
1397 if (module) {
1398 if (num_dumped++ > 0) {
1399 strm.EOL();
1400 strm.EOL();
1402 ObjectFile *objfile = module->GetObjectFile();
1403 if (objfile)
1404 objfile->Dump(&strm);
1405 else {
1406 strm.Format("No object file for module: {0:F}\n",
1407 module->GetFileSpec());
1411 strm.IndentLess();
1413 return num_dumped;
1416 static void DumpModuleSymtab(CommandInterpreter &interpreter, Stream &strm,
1417 Module *module, SortOrder sort_order,
1418 Mangled::NamePreference name_preference) {
1419 if (!module)
1420 return;
1421 if (Symtab *symtab = module->GetSymtab())
1422 symtab->Dump(&strm, interpreter.GetExecutionContext().GetTargetPtr(),
1423 sort_order, name_preference);
1426 static void DumpModuleSections(CommandInterpreter &interpreter, Stream &strm,
1427 Module *module) {
1428 if (module) {
1429 SectionList *section_list = module->GetSectionList();
1430 if (section_list) {
1431 strm.Printf("Sections for '%s' (%s):\n",
1432 module->GetSpecificationDescription().c_str(),
1433 module->GetArchitecture().GetArchitectureName());
1434 strm.IndentMore();
1435 section_list->Dump(&strm,
1436 interpreter.GetExecutionContext().GetTargetPtr(), true,
1437 UINT32_MAX);
1438 strm.IndentLess();
1443 static bool DumpModuleSymbolFile(Stream &strm, Module *module) {
1444 if (module) {
1445 if (SymbolFile *symbol_file = module->GetSymbolFile(true)) {
1446 symbol_file->Dump(strm);
1447 return true;
1450 return false;
1453 static void DumpAddress(ExecutionContextScope *exe_scope,
1454 const Address &so_addr, bool verbose, Stream &strm) {
1455 strm.IndentMore();
1456 strm.Indent(" Address: ");
1457 so_addr.Dump(&strm, exe_scope, Address::DumpStyleModuleWithFileAddress);
1458 strm.PutCString(" (");
1459 so_addr.Dump(&strm, exe_scope, Address::DumpStyleSectionNameOffset);
1460 strm.PutCString(")\n");
1461 strm.Indent(" Summary: ");
1462 const uint32_t save_indent = strm.GetIndentLevel();
1463 strm.SetIndentLevel(save_indent + 13);
1464 so_addr.Dump(&strm, exe_scope, Address::DumpStyleResolvedDescription);
1465 strm.SetIndentLevel(save_indent);
1466 // Print out detailed address information when verbose is enabled
1467 if (verbose) {
1468 strm.EOL();
1469 so_addr.Dump(&strm, exe_scope, Address::DumpStyleDetailedSymbolContext);
1471 strm.IndentLess();
1474 static bool LookupAddressInModule(CommandInterpreter &interpreter, Stream &strm,
1475 Module *module, uint32_t resolve_mask,
1476 lldb::addr_t raw_addr, lldb::addr_t offset,
1477 bool verbose) {
1478 if (module) {
1479 lldb::addr_t addr = raw_addr - offset;
1480 Address so_addr;
1481 SymbolContext sc;
1482 Target *target = interpreter.GetExecutionContext().GetTargetPtr();
1483 if (target && !target->GetSectionLoadList().IsEmpty()) {
1484 if (!target->GetSectionLoadList().ResolveLoadAddress(addr, so_addr))
1485 return false;
1486 else if (so_addr.GetModule().get() != module)
1487 return false;
1488 } else {
1489 if (!module->ResolveFileAddress(addr, so_addr))
1490 return false;
1493 ExecutionContextScope *exe_scope =
1494 interpreter.GetExecutionContext().GetBestExecutionContextScope();
1495 DumpAddress(exe_scope, so_addr, verbose, strm);
1496 // strm.IndentMore();
1497 // strm.Indent (" Address: ");
1498 // so_addr.Dump (&strm, exe_scope,
1499 // Address::DumpStyleModuleWithFileAddress);
1500 // strm.PutCString (" (");
1501 // so_addr.Dump (&strm, exe_scope,
1502 // Address::DumpStyleSectionNameOffset);
1503 // strm.PutCString (")\n");
1504 // strm.Indent (" Summary: ");
1505 // const uint32_t save_indent = strm.GetIndentLevel ();
1506 // strm.SetIndentLevel (save_indent + 13);
1507 // so_addr.Dump (&strm, exe_scope,
1508 // Address::DumpStyleResolvedDescription);
1509 // strm.SetIndentLevel (save_indent);
1510 // // Print out detailed address information when verbose is enabled
1511 // if (verbose)
1512 // {
1513 // strm.EOL();
1514 // so_addr.Dump (&strm, exe_scope,
1515 // Address::DumpStyleDetailedSymbolContext);
1516 // }
1517 // strm.IndentLess();
1518 return true;
1521 return false;
1524 static uint32_t LookupSymbolInModule(CommandInterpreter &interpreter,
1525 Stream &strm, Module *module,
1526 const char *name, bool name_is_regex,
1527 bool verbose) {
1528 if (!module)
1529 return 0;
1531 Symtab *symtab = module->GetSymtab();
1532 if (!symtab)
1533 return 0;
1535 SymbolContext sc;
1536 std::vector<uint32_t> match_indexes;
1537 ConstString symbol_name(name);
1538 uint32_t num_matches = 0;
1539 if (name_is_regex) {
1540 RegularExpression name_regexp(symbol_name.GetStringRef());
1541 num_matches = symtab->AppendSymbolIndexesMatchingRegExAndType(
1542 name_regexp, eSymbolTypeAny, match_indexes);
1543 } else {
1544 num_matches =
1545 symtab->AppendSymbolIndexesWithName(symbol_name, match_indexes);
1548 if (num_matches > 0) {
1549 strm.Indent();
1550 strm.Printf("%u symbols match %s'%s' in ", num_matches,
1551 name_is_regex ? "the regular expression " : "", name);
1552 DumpFullpath(strm, &module->GetFileSpec(), 0);
1553 strm.PutCString(":\n");
1554 strm.IndentMore();
1555 for (uint32_t i = 0; i < num_matches; ++i) {
1556 Symbol *symbol = symtab->SymbolAtIndex(match_indexes[i]);
1557 if (symbol && symbol->ValueIsAddress()) {
1558 DumpAddress(
1559 interpreter.GetExecutionContext().GetBestExecutionContextScope(),
1560 symbol->GetAddressRef(), verbose, strm);
1563 strm.IndentLess();
1565 return num_matches;
1568 static void DumpSymbolContextList(ExecutionContextScope *exe_scope,
1569 Stream &strm, SymbolContextList &sc_list,
1570 bool verbose) {
1571 strm.IndentMore();
1573 const uint32_t num_matches = sc_list.GetSize();
1575 for (uint32_t i = 0; i < num_matches; ++i) {
1576 SymbolContext sc;
1577 if (sc_list.GetContextAtIndex(i, sc)) {
1578 AddressRange range;
1580 sc.GetAddressRange(eSymbolContextEverything, 0, true, range);
1582 DumpAddress(exe_scope, range.GetBaseAddress(), verbose, strm);
1585 strm.IndentLess();
1588 static size_t LookupFunctionInModule(CommandInterpreter &interpreter,
1589 Stream &strm, Module *module,
1590 const char *name, bool name_is_regex,
1591 bool include_inlines, bool include_symbols,
1592 bool verbose) {
1593 if (module && name && name[0]) {
1594 SymbolContextList sc_list;
1595 size_t num_matches = 0;
1596 if (name_is_regex) {
1597 RegularExpression function_name_regex((llvm::StringRef(name)));
1598 module->FindFunctions(function_name_regex, include_symbols,
1599 include_inlines, sc_list);
1600 } else {
1601 ConstString function_name(name);
1602 module->FindFunctions(function_name, nullptr, eFunctionNameTypeAuto,
1603 include_symbols, include_inlines, sc_list);
1605 num_matches = sc_list.GetSize();
1606 if (num_matches) {
1607 strm.Indent();
1608 strm.Printf("%" PRIu64 " match%s found in ", (uint64_t)num_matches,
1609 num_matches > 1 ? "es" : "");
1610 DumpFullpath(strm, &module->GetFileSpec(), 0);
1611 strm.PutCString(":\n");
1612 DumpSymbolContextList(
1613 interpreter.GetExecutionContext().GetBestExecutionContextScope(),
1614 strm, sc_list, verbose);
1616 return num_matches;
1618 return 0;
1621 static size_t LookupTypeInModule(CommandInterpreter &interpreter, Stream &strm,
1622 Module *module, const char *name_cstr,
1623 bool name_is_regex) {
1624 TypeList type_list;
1625 if (module && name_cstr && name_cstr[0]) {
1626 const uint32_t max_num_matches = UINT32_MAX;
1627 size_t num_matches = 0;
1628 bool name_is_fully_qualified = false;
1630 ConstString name(name_cstr);
1631 llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files;
1632 module->FindTypes(name, name_is_fully_qualified, max_num_matches,
1633 searched_symbol_files, type_list);
1635 if (type_list.Empty())
1636 return 0;
1638 strm.Indent();
1639 strm.Printf("%" PRIu64 " match%s found in ", (uint64_t)num_matches,
1640 num_matches > 1 ? "es" : "");
1641 DumpFullpath(strm, &module->GetFileSpec(), 0);
1642 strm.PutCString(":\n");
1643 for (TypeSP type_sp : type_list.Types()) {
1644 if (!type_sp)
1645 continue;
1646 // Resolve the clang type so that any forward references to types
1647 // that haven't yet been parsed will get parsed.
1648 type_sp->GetFullCompilerType();
1649 type_sp->GetDescription(&strm, eDescriptionLevelFull, true);
1650 // Print all typedef chains
1651 TypeSP typedef_type_sp(type_sp);
1652 TypeSP typedefed_type_sp(typedef_type_sp->GetTypedefType());
1653 while (typedefed_type_sp) {
1654 strm.EOL();
1655 strm.Printf(" typedef '%s': ",
1656 typedef_type_sp->GetName().GetCString());
1657 typedefed_type_sp->GetFullCompilerType();
1658 typedefed_type_sp->GetDescription(&strm, eDescriptionLevelFull, true);
1659 typedef_type_sp = typedefed_type_sp;
1660 typedefed_type_sp = typedef_type_sp->GetTypedefType();
1663 strm.EOL();
1665 return type_list.GetSize();
1668 static size_t LookupTypeHere(CommandInterpreter &interpreter, Stream &strm,
1669 Module &module, const char *name_cstr,
1670 bool name_is_regex) {
1671 TypeList type_list;
1672 const uint32_t max_num_matches = UINT32_MAX;
1673 bool name_is_fully_qualified = false;
1675 ConstString name(name_cstr);
1676 llvm::DenseSet<SymbolFile *> searched_symbol_files;
1677 module.FindTypes(name, name_is_fully_qualified, max_num_matches,
1678 searched_symbol_files, type_list);
1680 if (type_list.Empty())
1681 return 0;
1683 strm.Indent();
1684 strm.PutCString("Best match found in ");
1685 DumpFullpath(strm, &module.GetFileSpec(), 0);
1686 strm.PutCString(":\n");
1688 TypeSP type_sp(type_list.GetTypeAtIndex(0));
1689 if (type_sp) {
1690 // Resolve the clang type so that any forward references to types that
1691 // haven't yet been parsed will get parsed.
1692 type_sp->GetFullCompilerType();
1693 type_sp->GetDescription(&strm, eDescriptionLevelFull, true);
1694 // Print all typedef chains
1695 TypeSP typedef_type_sp(type_sp);
1696 TypeSP typedefed_type_sp(typedef_type_sp->GetTypedefType());
1697 while (typedefed_type_sp) {
1698 strm.EOL();
1699 strm.Printf(" typedef '%s': ",
1700 typedef_type_sp->GetName().GetCString());
1701 typedefed_type_sp->GetFullCompilerType();
1702 typedefed_type_sp->GetDescription(&strm, eDescriptionLevelFull, true);
1703 typedef_type_sp = typedefed_type_sp;
1704 typedefed_type_sp = typedef_type_sp->GetTypedefType();
1707 strm.EOL();
1708 return type_list.GetSize();
1711 static uint32_t LookupFileAndLineInModule(CommandInterpreter &interpreter,
1712 Stream &strm, Module *module,
1713 const FileSpec &file_spec,
1714 uint32_t line, bool check_inlines,
1715 bool verbose) {
1716 if (module && file_spec) {
1717 SymbolContextList sc_list;
1718 const uint32_t num_matches = module->ResolveSymbolContextsForFileSpec(
1719 file_spec, line, check_inlines, eSymbolContextEverything, sc_list);
1720 if (num_matches > 0) {
1721 strm.Indent();
1722 strm.Printf("%u match%s found in ", num_matches,
1723 num_matches > 1 ? "es" : "");
1724 strm << file_spec;
1725 if (line > 0)
1726 strm.Printf(":%u", line);
1727 strm << " in ";
1728 DumpFullpath(strm, &module->GetFileSpec(), 0);
1729 strm.PutCString(":\n");
1730 DumpSymbolContextList(
1731 interpreter.GetExecutionContext().GetBestExecutionContextScope(),
1732 strm, sc_list, verbose);
1733 return num_matches;
1736 return 0;
1739 static size_t FindModulesByName(Target *target, const char *module_name,
1740 ModuleList &module_list,
1741 bool check_global_list) {
1742 FileSpec module_file_spec(module_name);
1743 ModuleSpec module_spec(module_file_spec);
1745 const size_t initial_size = module_list.GetSize();
1747 if (check_global_list) {
1748 // Check the global list
1749 std::lock_guard<std::recursive_mutex> guard(
1750 Module::GetAllocationModuleCollectionMutex());
1751 const size_t num_modules = Module::GetNumberAllocatedModules();
1752 ModuleSP module_sp;
1753 for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
1754 Module *module = Module::GetAllocatedModuleAtIndex(image_idx);
1756 if (module) {
1757 if (module->MatchesModuleSpec(module_spec)) {
1758 module_sp = module->shared_from_this();
1759 module_list.AppendIfNeeded(module_sp);
1763 } else {
1764 if (target) {
1765 target->GetImages().FindModules(module_spec, module_list);
1766 const size_t num_matches = module_list.GetSize();
1768 // Not found in our module list for our target, check the main shared
1769 // module list in case it is a extra file used somewhere else
1770 if (num_matches == 0) {
1771 module_spec.GetArchitecture() = target->GetArchitecture();
1772 ModuleList::FindSharedModules(module_spec, module_list);
1774 } else {
1775 ModuleList::FindSharedModules(module_spec, module_list);
1779 return module_list.GetSize() - initial_size;
1782 #pragma mark CommandObjectTargetModulesModuleAutoComplete
1784 // A base command object class that can auto complete with module file
1785 // paths
1787 class CommandObjectTargetModulesModuleAutoComplete
1788 : public CommandObjectParsed {
1789 public:
1790 CommandObjectTargetModulesModuleAutoComplete(CommandInterpreter &interpreter,
1791 const char *name,
1792 const char *help,
1793 const char *syntax,
1794 uint32_t flags = 0)
1795 : CommandObjectParsed(interpreter, name, help, syntax, flags) {
1796 CommandArgumentEntry arg;
1797 CommandArgumentData file_arg;
1799 // Define the first (and only) variant of this arg.
1800 file_arg.arg_type = eArgTypeFilename;
1801 file_arg.arg_repetition = eArgRepeatStar;
1803 // There is only one variant this argument could be; put it into the
1804 // argument entry.
1805 arg.push_back(file_arg);
1807 // Push the data for the first argument into the m_arguments vector.
1808 m_arguments.push_back(arg);
1811 ~CommandObjectTargetModulesModuleAutoComplete() override = default;
1813 void
1814 HandleArgumentCompletion(CompletionRequest &request,
1815 OptionElementVector &opt_element_vector) override {
1816 CommandCompletions::InvokeCommonCompletionCallbacks(
1817 GetCommandInterpreter(), CommandCompletions::eModuleCompletion, request,
1818 nullptr);
1822 #pragma mark CommandObjectTargetModulesSourceFileAutoComplete
1824 // A base command object class that can auto complete with module source
1825 // file paths
1827 class CommandObjectTargetModulesSourceFileAutoComplete
1828 : public CommandObjectParsed {
1829 public:
1830 CommandObjectTargetModulesSourceFileAutoComplete(
1831 CommandInterpreter &interpreter, const char *name, const char *help,
1832 const char *syntax, uint32_t flags)
1833 : CommandObjectParsed(interpreter, name, help, syntax, flags) {
1834 CommandArgumentEntry arg;
1835 CommandArgumentData source_file_arg;
1837 // Define the first (and only) variant of this arg.
1838 source_file_arg.arg_type = eArgTypeSourceFile;
1839 source_file_arg.arg_repetition = eArgRepeatPlus;
1841 // There is only one variant this argument could be; put it into the
1842 // argument entry.
1843 arg.push_back(source_file_arg);
1845 // Push the data for the first argument into the m_arguments vector.
1846 m_arguments.push_back(arg);
1849 ~CommandObjectTargetModulesSourceFileAutoComplete() override = default;
1851 void
1852 HandleArgumentCompletion(CompletionRequest &request,
1853 OptionElementVector &opt_element_vector) override {
1854 CommandCompletions::InvokeCommonCompletionCallbacks(
1855 GetCommandInterpreter(), CommandCompletions::eSourceFileCompletion,
1856 request, nullptr);
1860 #pragma mark CommandObjectTargetModulesDumpObjfile
1862 class CommandObjectTargetModulesDumpObjfile
1863 : public CommandObjectTargetModulesModuleAutoComplete {
1864 public:
1865 CommandObjectTargetModulesDumpObjfile(CommandInterpreter &interpreter)
1866 : CommandObjectTargetModulesModuleAutoComplete(
1867 interpreter, "target modules dump objfile",
1868 "Dump the object file headers from one or more target modules.",
1869 nullptr, eCommandRequiresTarget) {}
1871 ~CommandObjectTargetModulesDumpObjfile() override = default;
1873 protected:
1874 bool DoExecute(Args &command, CommandReturnObject &result) override {
1875 Target *target = &GetSelectedTarget();
1877 uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
1878 result.GetOutputStream().SetAddressByteSize(addr_byte_size);
1879 result.GetErrorStream().SetAddressByteSize(addr_byte_size);
1881 size_t num_dumped = 0;
1882 if (command.GetArgumentCount() == 0) {
1883 // Dump all headers for all modules images
1884 num_dumped = DumpModuleObjfileHeaders(result.GetOutputStream(),
1885 target->GetImages());
1886 if (num_dumped == 0) {
1887 result.AppendError("the target has no associated executable images");
1888 result.SetStatus(eReturnStatusFailed);
1890 } else {
1891 // Find the modules that match the basename or full path.
1892 ModuleList module_list;
1893 const char *arg_cstr;
1894 for (int arg_idx = 0;
1895 (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
1896 ++arg_idx) {
1897 size_t num_matched =
1898 FindModulesByName(target, arg_cstr, module_list, true);
1899 if (num_matched == 0) {
1900 result.AppendWarningWithFormat(
1901 "Unable to find an image that matches '%s'.\n", arg_cstr);
1904 // Dump all the modules we found.
1905 num_dumped =
1906 DumpModuleObjfileHeaders(result.GetOutputStream(), module_list);
1909 if (num_dumped > 0) {
1910 result.SetStatus(eReturnStatusSuccessFinishResult);
1911 } else {
1912 result.AppendError("no matching executable images found");
1913 result.SetStatus(eReturnStatusFailed);
1915 return result.Succeeded();
1919 #pragma mark CommandObjectTargetModulesDumpSymtab
1921 static constexpr OptionEnumValueElement g_sort_option_enumeration[] = {
1923 eSortOrderNone,
1924 "none",
1925 "No sorting, use the original symbol table order.",
1928 eSortOrderByAddress,
1929 "address",
1930 "Sort output by symbol address.",
1933 eSortOrderByName,
1934 "name",
1935 "Sort output by symbol name.",
1939 #define LLDB_OPTIONS_target_modules_dump_symtab
1940 #include "CommandOptions.inc"
1942 class CommandObjectTargetModulesDumpSymtab
1943 : public CommandObjectTargetModulesModuleAutoComplete {
1944 public:
1945 CommandObjectTargetModulesDumpSymtab(CommandInterpreter &interpreter)
1946 : CommandObjectTargetModulesModuleAutoComplete(
1947 interpreter, "target modules dump symtab",
1948 "Dump the symbol table from one or more target modules.", nullptr,
1949 eCommandRequiresTarget),
1950 m_options() {}
1952 ~CommandObjectTargetModulesDumpSymtab() override = default;
1954 Options *GetOptions() override { return &m_options; }
1956 class CommandOptions : public Options {
1957 public:
1958 CommandOptions() : Options(), m_sort_order(eSortOrderNone) {}
1960 ~CommandOptions() override = default;
1962 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1963 ExecutionContext *execution_context) override {
1964 Status error;
1965 const int short_option = m_getopt_table[option_idx].val;
1967 switch (short_option) {
1968 case 'm':
1969 m_prefer_mangled.SetCurrentValue(true);
1970 m_prefer_mangled.SetOptionWasSet();
1971 break;
1973 case 's':
1974 m_sort_order = (SortOrder)OptionArgParser::ToOptionEnum(
1975 option_arg, GetDefinitions()[option_idx].enum_values,
1976 eSortOrderNone, error);
1977 break;
1979 default:
1980 llvm_unreachable("Unimplemented option");
1982 return error;
1985 void OptionParsingStarting(ExecutionContext *execution_context) override {
1986 m_sort_order = eSortOrderNone;
1987 m_prefer_mangled.Clear();
1990 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1991 return llvm::makeArrayRef(g_target_modules_dump_symtab_options);
1994 SortOrder m_sort_order;
1995 OptionValueBoolean m_prefer_mangled = {false, false};
1998 protected:
1999 bool DoExecute(Args &command, CommandReturnObject &result) override {
2000 Target *target = &GetSelectedTarget();
2001 uint32_t num_dumped = 0;
2002 Mangled::NamePreference name_preference =
2003 (m_options.m_prefer_mangled ? Mangled::ePreferMangled
2004 : Mangled::ePreferDemangled);
2006 uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
2007 result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2008 result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2010 if (command.GetArgumentCount() == 0) {
2011 // Dump all sections for all modules images
2012 std::lock_guard<std::recursive_mutex> guard(
2013 target->GetImages().GetMutex());
2014 const size_t num_modules = target->GetImages().GetSize();
2015 if (num_modules > 0) {
2016 result.GetOutputStream().Printf("Dumping symbol table for %" PRIu64
2017 " modules.\n",
2018 (uint64_t)num_modules);
2019 for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
2020 if (num_dumped > 0) {
2021 result.GetOutputStream().EOL();
2022 result.GetOutputStream().EOL();
2024 if (m_interpreter.WasInterrupted())
2025 break;
2026 num_dumped++;
2027 DumpModuleSymtab(
2028 m_interpreter, result.GetOutputStream(),
2029 target->GetImages().GetModulePointerAtIndexUnlocked(image_idx),
2030 m_options.m_sort_order, name_preference);
2032 } else {
2033 result.AppendError("the target has no associated executable images");
2034 result.SetStatus(eReturnStatusFailed);
2035 return false;
2037 } else {
2038 // Dump specified images (by basename or fullpath)
2039 const char *arg_cstr;
2040 for (int arg_idx = 0;
2041 (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
2042 ++arg_idx) {
2043 ModuleList module_list;
2044 const size_t num_matches =
2045 FindModulesByName(target, arg_cstr, module_list, true);
2046 if (num_matches > 0) {
2047 for (size_t i = 0; i < num_matches; ++i) {
2048 Module *module = module_list.GetModulePointerAtIndex(i);
2049 if (module) {
2050 if (num_dumped > 0) {
2051 result.GetOutputStream().EOL();
2052 result.GetOutputStream().EOL();
2054 if (m_interpreter.WasInterrupted())
2055 break;
2056 num_dumped++;
2057 DumpModuleSymtab(m_interpreter, result.GetOutputStream(), module,
2058 m_options.m_sort_order, name_preference);
2061 } else
2062 result.AppendWarningWithFormat(
2063 "Unable to find an image that matches '%s'.\n", arg_cstr);
2067 if (num_dumped > 0)
2068 result.SetStatus(eReturnStatusSuccessFinishResult);
2069 else {
2070 result.AppendError("no matching executable images found");
2071 result.SetStatus(eReturnStatusFailed);
2073 return result.Succeeded();
2076 CommandOptions m_options;
2079 #pragma mark CommandObjectTargetModulesDumpSections
2081 // Image section dumping command
2083 class CommandObjectTargetModulesDumpSections
2084 : public CommandObjectTargetModulesModuleAutoComplete {
2085 public:
2086 CommandObjectTargetModulesDumpSections(CommandInterpreter &interpreter)
2087 : CommandObjectTargetModulesModuleAutoComplete(
2088 interpreter, "target modules dump sections",
2089 "Dump the sections from one or more target modules.",
2090 //"target modules dump sections [<file1> ...]")
2091 nullptr, eCommandRequiresTarget) {}
2093 ~CommandObjectTargetModulesDumpSections() override = default;
2095 protected:
2096 bool DoExecute(Args &command, CommandReturnObject &result) override {
2097 Target *target = &GetSelectedTarget();
2098 uint32_t num_dumped = 0;
2100 uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
2101 result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2102 result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2104 if (command.GetArgumentCount() == 0) {
2105 // Dump all sections for all modules images
2106 const size_t num_modules = target->GetImages().GetSize();
2107 if (num_modules > 0) {
2108 result.GetOutputStream().Printf("Dumping sections for %" PRIu64
2109 " modules.\n",
2110 (uint64_t)num_modules);
2111 for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
2112 if (m_interpreter.WasInterrupted())
2113 break;
2114 num_dumped++;
2115 DumpModuleSections(
2116 m_interpreter, result.GetOutputStream(),
2117 target->GetImages().GetModulePointerAtIndex(image_idx));
2119 } else {
2120 result.AppendError("the target has no associated executable images");
2121 result.SetStatus(eReturnStatusFailed);
2122 return false;
2124 } else {
2125 // Dump specified images (by basename or fullpath)
2126 const char *arg_cstr;
2127 for (int arg_idx = 0;
2128 (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
2129 ++arg_idx) {
2130 ModuleList module_list;
2131 const size_t num_matches =
2132 FindModulesByName(target, arg_cstr, module_list, true);
2133 if (num_matches > 0) {
2134 for (size_t i = 0; i < num_matches; ++i) {
2135 if (m_interpreter.WasInterrupted())
2136 break;
2137 Module *module = module_list.GetModulePointerAtIndex(i);
2138 if (module) {
2139 num_dumped++;
2140 DumpModuleSections(m_interpreter, result.GetOutputStream(),
2141 module);
2144 } else {
2145 // Check the global list
2146 std::lock_guard<std::recursive_mutex> guard(
2147 Module::GetAllocationModuleCollectionMutex());
2149 result.AppendWarningWithFormat(
2150 "Unable to find an image that matches '%s'.\n", arg_cstr);
2155 if (num_dumped > 0)
2156 result.SetStatus(eReturnStatusSuccessFinishResult);
2157 else {
2158 result.AppendError("no matching executable images found");
2159 result.SetStatus(eReturnStatusFailed);
2161 return result.Succeeded();
2165 #pragma mark CommandObjectTargetModulesDumpSections
2167 // Clang AST dumping command
2169 class CommandObjectTargetModulesDumpClangAST
2170 : public CommandObjectTargetModulesModuleAutoComplete {
2171 public:
2172 CommandObjectTargetModulesDumpClangAST(CommandInterpreter &interpreter)
2173 : CommandObjectTargetModulesModuleAutoComplete(
2174 interpreter, "target modules dump ast",
2175 "Dump the clang ast for a given module's symbol file.",
2176 //"target modules dump ast [<file1> ...]")
2177 nullptr, eCommandRequiresTarget) {}
2179 ~CommandObjectTargetModulesDumpClangAST() override = default;
2181 protected:
2182 bool DoExecute(Args &command, CommandReturnObject &result) override {
2183 Target *target = &GetSelectedTarget();
2185 const size_t num_modules = target->GetImages().GetSize();
2186 if (num_modules == 0) {
2187 result.AppendError("the target has no associated executable images");
2188 result.SetStatus(eReturnStatusFailed);
2189 return false;
2192 if (command.GetArgumentCount() == 0) {
2193 // Dump all ASTs for all modules images
2194 result.GetOutputStream().Printf("Dumping clang ast for %" PRIu64
2195 " modules.\n",
2196 (uint64_t)num_modules);
2197 for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
2198 if (m_interpreter.WasInterrupted())
2199 break;
2200 Module *m = target->GetImages().GetModulePointerAtIndex(image_idx);
2201 if (SymbolFile *sf = m->GetSymbolFile())
2202 sf->DumpClangAST(result.GetOutputStream());
2204 result.SetStatus(eReturnStatusSuccessFinishResult);
2205 return true;
2208 // Dump specified ASTs (by basename or fullpath)
2209 for (const Args::ArgEntry &arg : command.entries()) {
2210 ModuleList module_list;
2211 const size_t num_matches =
2212 FindModulesByName(target, arg.c_str(), module_list, true);
2213 if (num_matches == 0) {
2214 // Check the global list
2215 std::lock_guard<std::recursive_mutex> guard(
2216 Module::GetAllocationModuleCollectionMutex());
2218 result.AppendWarningWithFormat(
2219 "Unable to find an image that matches '%s'.\n", arg.c_str());
2220 continue;
2223 for (size_t i = 0; i < num_matches; ++i) {
2224 if (m_interpreter.WasInterrupted())
2225 break;
2226 Module *m = module_list.GetModulePointerAtIndex(i);
2227 if (SymbolFile *sf = m->GetSymbolFile())
2228 sf->DumpClangAST(result.GetOutputStream());
2231 result.SetStatus(eReturnStatusSuccessFinishResult);
2232 return true;
2236 #pragma mark CommandObjectTargetModulesDumpSymfile
2238 // Image debug symbol dumping command
2240 class CommandObjectTargetModulesDumpSymfile
2241 : public CommandObjectTargetModulesModuleAutoComplete {
2242 public:
2243 CommandObjectTargetModulesDumpSymfile(CommandInterpreter &interpreter)
2244 : CommandObjectTargetModulesModuleAutoComplete(
2245 interpreter, "target modules dump symfile",
2246 "Dump the debug symbol file for one or more target modules.",
2247 //"target modules dump symfile [<file1> ...]")
2248 nullptr, eCommandRequiresTarget) {}
2250 ~CommandObjectTargetModulesDumpSymfile() override = default;
2252 protected:
2253 bool DoExecute(Args &command, CommandReturnObject &result) override {
2254 Target *target = &GetSelectedTarget();
2255 uint32_t num_dumped = 0;
2257 uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
2258 result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2259 result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2261 if (command.GetArgumentCount() == 0) {
2262 // Dump all sections for all modules images
2263 const ModuleList &target_modules = target->GetImages();
2264 std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
2265 const size_t num_modules = target_modules.GetSize();
2266 if (num_modules > 0) {
2267 result.GetOutputStream().Printf("Dumping debug symbols for %" PRIu64
2268 " modules.\n",
2269 (uint64_t)num_modules);
2270 for (uint32_t image_idx = 0; image_idx < num_modules; ++image_idx) {
2271 if (m_interpreter.WasInterrupted())
2272 break;
2273 if (DumpModuleSymbolFile(
2274 result.GetOutputStream(),
2275 target_modules.GetModulePointerAtIndexUnlocked(image_idx)))
2276 num_dumped++;
2278 } else {
2279 result.AppendError("the target has no associated executable images");
2280 result.SetStatus(eReturnStatusFailed);
2281 return false;
2283 } else {
2284 // Dump specified images (by basename or fullpath)
2285 const char *arg_cstr;
2286 for (int arg_idx = 0;
2287 (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
2288 ++arg_idx) {
2289 ModuleList module_list;
2290 const size_t num_matches =
2291 FindModulesByName(target, arg_cstr, module_list, true);
2292 if (num_matches > 0) {
2293 for (size_t i = 0; i < num_matches; ++i) {
2294 if (m_interpreter.WasInterrupted())
2295 break;
2296 Module *module = module_list.GetModulePointerAtIndex(i);
2297 if (module) {
2298 if (DumpModuleSymbolFile(result.GetOutputStream(), module))
2299 num_dumped++;
2302 } else
2303 result.AppendWarningWithFormat(
2304 "Unable to find an image that matches '%s'.\n", arg_cstr);
2308 if (num_dumped > 0)
2309 result.SetStatus(eReturnStatusSuccessFinishResult);
2310 else {
2311 result.AppendError("no matching executable images found");
2312 result.SetStatus(eReturnStatusFailed);
2314 return result.Succeeded();
2318 #pragma mark CommandObjectTargetModulesDumpLineTable
2319 #define LLDB_OPTIONS_target_modules_dump
2320 #include "CommandOptions.inc"
2322 // Image debug line table dumping command
2324 class CommandObjectTargetModulesDumpLineTable
2325 : public CommandObjectTargetModulesSourceFileAutoComplete {
2326 public:
2327 CommandObjectTargetModulesDumpLineTable(CommandInterpreter &interpreter)
2328 : CommandObjectTargetModulesSourceFileAutoComplete(
2329 interpreter, "target modules dump line-table",
2330 "Dump the line table for one or more compilation units.", nullptr,
2331 eCommandRequiresTarget) {}
2333 ~CommandObjectTargetModulesDumpLineTable() override = default;
2335 Options *GetOptions() override { return &m_options; }
2337 protected:
2338 bool DoExecute(Args &command, CommandReturnObject &result) override {
2339 Target *target = m_exe_ctx.GetTargetPtr();
2340 uint32_t total_num_dumped = 0;
2342 uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
2343 result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2344 result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2346 if (command.GetArgumentCount() == 0) {
2347 result.AppendError("file option must be specified.");
2348 result.SetStatus(eReturnStatusFailed);
2349 return result.Succeeded();
2350 } else {
2351 // Dump specified images (by basename or fullpath)
2352 const char *arg_cstr;
2353 for (int arg_idx = 0;
2354 (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
2355 ++arg_idx) {
2356 FileSpec file_spec(arg_cstr);
2358 const ModuleList &target_modules = target->GetImages();
2359 std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
2360 const size_t num_modules = target_modules.GetSize();
2361 if (num_modules > 0) {
2362 uint32_t num_dumped = 0;
2363 for (uint32_t i = 0; i < num_modules; ++i) {
2364 if (m_interpreter.WasInterrupted())
2365 break;
2366 if (DumpCompileUnitLineTable(
2367 m_interpreter, result.GetOutputStream(),
2368 target_modules.GetModulePointerAtIndexUnlocked(i),
2369 file_spec,
2370 m_options.m_verbose ? eDescriptionLevelFull
2371 : eDescriptionLevelBrief))
2372 num_dumped++;
2374 if (num_dumped == 0)
2375 result.AppendWarningWithFormat(
2376 "No source filenames matched '%s'.\n", arg_cstr);
2377 else
2378 total_num_dumped += num_dumped;
2383 if (total_num_dumped > 0)
2384 result.SetStatus(eReturnStatusSuccessFinishResult);
2385 else {
2386 result.AppendError("no source filenames matched any command arguments");
2387 result.SetStatus(eReturnStatusFailed);
2389 return result.Succeeded();
2392 class CommandOptions : public Options {
2393 public:
2394 CommandOptions() : Options() { OptionParsingStarting(nullptr); }
2396 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2397 ExecutionContext *execution_context) override {
2398 assert(option_idx == 0 && "We only have one option.");
2399 m_verbose = true;
2401 return Status();
2404 void OptionParsingStarting(ExecutionContext *execution_context) override {
2405 m_verbose = false;
2408 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2409 return llvm::makeArrayRef(g_target_modules_dump_options);
2412 bool m_verbose;
2415 CommandOptions m_options;
2418 #pragma mark CommandObjectTargetModulesDump
2420 // Dump multi-word command for target modules
2422 class CommandObjectTargetModulesDump : public CommandObjectMultiword {
2423 public:
2424 // Constructors and Destructors
2425 CommandObjectTargetModulesDump(CommandInterpreter &interpreter)
2426 : CommandObjectMultiword(
2427 interpreter, "target modules dump",
2428 "Commands for dumping information about one or "
2429 "more target modules.",
2430 "target modules dump "
2431 "[headers|symtab|sections|ast|symfile|line-table] "
2432 "[<file1> <file2> ...]") {
2433 LoadSubCommand("objfile",
2434 CommandObjectSP(
2435 new CommandObjectTargetModulesDumpObjfile(interpreter)));
2436 LoadSubCommand(
2437 "symtab",
2438 CommandObjectSP(new CommandObjectTargetModulesDumpSymtab(interpreter)));
2439 LoadSubCommand("sections",
2440 CommandObjectSP(new CommandObjectTargetModulesDumpSections(
2441 interpreter)));
2442 LoadSubCommand("symfile",
2443 CommandObjectSP(
2444 new CommandObjectTargetModulesDumpSymfile(interpreter)));
2445 LoadSubCommand(
2446 "ast", CommandObjectSP(
2447 new CommandObjectTargetModulesDumpClangAST(interpreter)));
2448 LoadSubCommand("line-table",
2449 CommandObjectSP(new CommandObjectTargetModulesDumpLineTable(
2450 interpreter)));
2453 ~CommandObjectTargetModulesDump() override = default;
2456 class CommandObjectTargetModulesAdd : public CommandObjectParsed {
2457 public:
2458 CommandObjectTargetModulesAdd(CommandInterpreter &interpreter)
2459 : CommandObjectParsed(interpreter, "target modules add",
2460 "Add a new module to the current target's modules.",
2461 "target modules add [<module>]",
2462 eCommandRequiresTarget),
2463 m_option_group(), m_symbol_file(LLDB_OPT_SET_1, false, "symfile", 's',
2464 0, eArgTypeFilename,
2465 "Fullpath to a stand alone debug "
2466 "symbols file for when debug symbols "
2467 "are not in the executable.") {
2468 m_option_group.Append(&m_uuid_option_group, LLDB_OPT_SET_ALL,
2469 LLDB_OPT_SET_1);
2470 m_option_group.Append(&m_symbol_file, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2471 m_option_group.Finalize();
2474 ~CommandObjectTargetModulesAdd() override = default;
2476 Options *GetOptions() override { return &m_option_group; }
2478 void
2479 HandleArgumentCompletion(CompletionRequest &request,
2480 OptionElementVector &opt_element_vector) override {
2481 CommandCompletions::InvokeCommonCompletionCallbacks(
2482 GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
2483 request, nullptr);
2486 protected:
2487 OptionGroupOptions m_option_group;
2488 OptionGroupUUID m_uuid_option_group;
2489 OptionGroupFile m_symbol_file;
2491 bool DoExecute(Args &args, CommandReturnObject &result) override {
2492 Target *target = &GetSelectedTarget();
2493 bool flush = false;
2495 const size_t argc = args.GetArgumentCount();
2496 if (argc == 0) {
2497 if (m_uuid_option_group.GetOptionValue().OptionWasSet()) {
2498 // We are given a UUID only, go locate the file
2499 ModuleSpec module_spec;
2500 module_spec.GetUUID() =
2501 m_uuid_option_group.GetOptionValue().GetCurrentValue();
2502 if (m_symbol_file.GetOptionValue().OptionWasSet())
2503 module_spec.GetSymbolFileSpec() =
2504 m_symbol_file.GetOptionValue().GetCurrentValue();
2505 if (Symbols::DownloadObjectAndSymbolFile(module_spec)) {
2506 ModuleSP module_sp(
2507 target->GetOrCreateModule(module_spec, true /* notify */));
2508 if (module_sp) {
2509 result.SetStatus(eReturnStatusSuccessFinishResult);
2510 return true;
2511 } else {
2512 StreamString strm;
2513 module_spec.GetUUID().Dump(&strm);
2514 if (module_spec.GetFileSpec()) {
2515 if (module_spec.GetSymbolFileSpec()) {
2516 result.AppendErrorWithFormat(
2517 "Unable to create the executable or symbol file with "
2518 "UUID %s with path %s and symbol file %s",
2519 strm.GetData(), module_spec.GetFileSpec().GetPath().c_str(),
2520 module_spec.GetSymbolFileSpec().GetPath().c_str());
2521 } else {
2522 result.AppendErrorWithFormat(
2523 "Unable to create the executable or symbol file with "
2524 "UUID %s with path %s",
2525 strm.GetData(),
2526 module_spec.GetFileSpec().GetPath().c_str());
2528 } else {
2529 result.AppendErrorWithFormat("Unable to create the executable "
2530 "or symbol file with UUID %s",
2531 strm.GetData());
2533 result.SetStatus(eReturnStatusFailed);
2534 return false;
2536 } else {
2537 StreamString strm;
2538 module_spec.GetUUID().Dump(&strm);
2539 result.AppendErrorWithFormat(
2540 "Unable to locate the executable or symbol file with UUID %s",
2541 strm.GetData());
2542 result.SetStatus(eReturnStatusFailed);
2543 return false;
2545 } else {
2546 result.AppendError(
2547 "one or more executable image paths must be specified");
2548 result.SetStatus(eReturnStatusFailed);
2549 return false;
2551 } else {
2552 for (auto &entry : args.entries()) {
2553 if (entry.ref().empty())
2554 continue;
2556 FileSpec file_spec(entry.ref());
2557 if (FileSystem::Instance().Exists(file_spec)) {
2558 ModuleSpec module_spec(file_spec);
2559 if (m_uuid_option_group.GetOptionValue().OptionWasSet())
2560 module_spec.GetUUID() =
2561 m_uuid_option_group.GetOptionValue().GetCurrentValue();
2562 if (m_symbol_file.GetOptionValue().OptionWasSet())
2563 module_spec.GetSymbolFileSpec() =
2564 m_symbol_file.GetOptionValue().GetCurrentValue();
2565 if (!module_spec.GetArchitecture().IsValid())
2566 module_spec.GetArchitecture() = target->GetArchitecture();
2567 Status error;
2568 ModuleSP module_sp(target->GetOrCreateModule(
2569 module_spec, true /* notify */, &error));
2570 if (!module_sp) {
2571 const char *error_cstr = error.AsCString();
2572 if (error_cstr)
2573 result.AppendError(error_cstr);
2574 else
2575 result.AppendErrorWithFormat("unsupported module: %s",
2576 entry.c_str());
2577 result.SetStatus(eReturnStatusFailed);
2578 return false;
2579 } else {
2580 flush = true;
2582 result.SetStatus(eReturnStatusSuccessFinishResult);
2583 } else {
2584 std::string resolved_path = file_spec.GetPath();
2585 result.SetStatus(eReturnStatusFailed);
2586 if (resolved_path != entry.ref()) {
2587 result.AppendErrorWithFormat(
2588 "invalid module path '%s' with resolved path '%s'\n",
2589 entry.ref().str().c_str(), resolved_path.c_str());
2590 break;
2592 result.AppendErrorWithFormat("invalid module path '%s'\n",
2593 entry.c_str());
2594 break;
2599 if (flush) {
2600 ProcessSP process = target->GetProcessSP();
2601 if (process)
2602 process->Flush();
2605 return result.Succeeded();
2609 class CommandObjectTargetModulesLoad
2610 : public CommandObjectTargetModulesModuleAutoComplete {
2611 public:
2612 CommandObjectTargetModulesLoad(CommandInterpreter &interpreter)
2613 : CommandObjectTargetModulesModuleAutoComplete(
2614 interpreter, "target modules load",
2615 "Set the load addresses for one or more sections in a target "
2616 "module.",
2617 "target modules load [--file <module> --uuid <uuid>] <sect-name> "
2618 "<address> [<sect-name> <address> ....]",
2619 eCommandRequiresTarget),
2620 m_option_group(),
2621 m_file_option(LLDB_OPT_SET_1, false, "file", 'f', 0, eArgTypeName,
2622 "Fullpath or basename for module to load.", ""),
2623 m_load_option(LLDB_OPT_SET_1, false, "load", 'l',
2624 "Write file contents to the memory.", false, true),
2625 m_pc_option(LLDB_OPT_SET_1, false, "set-pc-to-entry", 'p',
2626 "Set PC to the entry point."
2627 " Only applicable with '--load' option.",
2628 false, true),
2629 m_slide_option(LLDB_OPT_SET_1, false, "slide", 's', 0, eArgTypeOffset,
2630 "Set the load address for all sections to be the "
2631 "virtual address in the file plus the offset.",
2632 0) {
2633 m_option_group.Append(&m_uuid_option_group, LLDB_OPT_SET_ALL,
2634 LLDB_OPT_SET_1);
2635 m_option_group.Append(&m_file_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2636 m_option_group.Append(&m_load_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2637 m_option_group.Append(&m_pc_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2638 m_option_group.Append(&m_slide_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
2639 m_option_group.Finalize();
2642 ~CommandObjectTargetModulesLoad() override = default;
2644 Options *GetOptions() override { return &m_option_group; }
2646 protected:
2647 bool DoExecute(Args &args, CommandReturnObject &result) override {
2648 Target *target = &GetSelectedTarget();
2649 const bool load = m_load_option.GetOptionValue().GetCurrentValue();
2650 const bool set_pc = m_pc_option.GetOptionValue().GetCurrentValue();
2652 const size_t argc = args.GetArgumentCount();
2653 ModuleSpec module_spec;
2654 bool search_using_module_spec = false;
2656 // Allow "load" option to work without --file or --uuid option.
2657 if (load) {
2658 if (!m_file_option.GetOptionValue().OptionWasSet() &&
2659 !m_uuid_option_group.GetOptionValue().OptionWasSet()) {
2660 ModuleList &module_list = target->GetImages();
2661 if (module_list.GetSize() == 1) {
2662 search_using_module_spec = true;
2663 module_spec.GetFileSpec() =
2664 module_list.GetModuleAtIndex(0)->GetFileSpec();
2669 if (m_file_option.GetOptionValue().OptionWasSet()) {
2670 search_using_module_spec = true;
2671 const char *arg_cstr = m_file_option.GetOptionValue().GetCurrentValue();
2672 const bool use_global_module_list = true;
2673 ModuleList module_list;
2674 const size_t num_matches = FindModulesByName(
2675 target, arg_cstr, module_list, use_global_module_list);
2676 if (num_matches == 1) {
2677 module_spec.GetFileSpec() =
2678 module_list.GetModuleAtIndex(0)->GetFileSpec();
2679 } else if (num_matches > 1) {
2680 search_using_module_spec = false;
2681 result.AppendErrorWithFormat(
2682 "more than 1 module matched by name '%s'\n", arg_cstr);
2683 result.SetStatus(eReturnStatusFailed);
2684 } else {
2685 search_using_module_spec = false;
2686 result.AppendErrorWithFormat("no object file for module '%s'\n",
2687 arg_cstr);
2688 result.SetStatus(eReturnStatusFailed);
2692 if (m_uuid_option_group.GetOptionValue().OptionWasSet()) {
2693 search_using_module_spec = true;
2694 module_spec.GetUUID() =
2695 m_uuid_option_group.GetOptionValue().GetCurrentValue();
2698 if (search_using_module_spec) {
2699 ModuleList matching_modules;
2700 target->GetImages().FindModules(module_spec, matching_modules);
2701 const size_t num_matches = matching_modules.GetSize();
2703 char path[PATH_MAX];
2704 if (num_matches == 1) {
2705 Module *module = matching_modules.GetModulePointerAtIndex(0);
2706 if (module) {
2707 ObjectFile *objfile = module->GetObjectFile();
2708 if (objfile) {
2709 SectionList *section_list = module->GetSectionList();
2710 if (section_list) {
2711 bool changed = false;
2712 if (argc == 0) {
2713 if (m_slide_option.GetOptionValue().OptionWasSet()) {
2714 const addr_t slide =
2715 m_slide_option.GetOptionValue().GetCurrentValue();
2716 const bool slide_is_offset = true;
2717 module->SetLoadAddress(*target, slide, slide_is_offset,
2718 changed);
2719 } else {
2720 result.AppendError("one or more section name + load "
2721 "address pair must be specified");
2722 result.SetStatus(eReturnStatusFailed);
2723 return false;
2725 } else {
2726 if (m_slide_option.GetOptionValue().OptionWasSet()) {
2727 result.AppendError("The \"--slide <offset>\" option can't "
2728 "be used in conjunction with setting "
2729 "section load addresses.\n");
2730 result.SetStatus(eReturnStatusFailed);
2731 return false;
2734 for (size_t i = 0; i < argc; i += 2) {
2735 const char *sect_name = args.GetArgumentAtIndex(i);
2736 const char *load_addr_cstr = args.GetArgumentAtIndex(i + 1);
2737 if (sect_name && load_addr_cstr) {
2738 ConstString const_sect_name(sect_name);
2739 bool success = false;
2740 addr_t load_addr = StringConvert::ToUInt64(
2741 load_addr_cstr, LLDB_INVALID_ADDRESS, 0, &success);
2742 if (success) {
2743 SectionSP section_sp(
2744 section_list->FindSectionByName(const_sect_name));
2745 if (section_sp) {
2746 if (section_sp->IsThreadSpecific()) {
2747 result.AppendErrorWithFormat(
2748 "thread specific sections are not yet "
2749 "supported (section '%s')\n",
2750 sect_name);
2751 result.SetStatus(eReturnStatusFailed);
2752 break;
2753 } else {
2754 if (target->GetSectionLoadList()
2755 .SetSectionLoadAddress(section_sp, load_addr))
2756 changed = true;
2757 result.AppendMessageWithFormat(
2758 "section '%s' loaded at 0x%" PRIx64 "\n",
2759 sect_name, load_addr);
2761 } else {
2762 result.AppendErrorWithFormat("no section found that "
2763 "matches the section "
2764 "name '%s'\n",
2765 sect_name);
2766 result.SetStatus(eReturnStatusFailed);
2767 break;
2769 } else {
2770 result.AppendErrorWithFormat(
2771 "invalid load address string '%s'\n", load_addr_cstr);
2772 result.SetStatus(eReturnStatusFailed);
2773 break;
2775 } else {
2776 if (sect_name)
2777 result.AppendError("section names must be followed by "
2778 "a load address.\n");
2779 else
2780 result.AppendError("one or more section name + load "
2781 "address pair must be specified.\n");
2782 result.SetStatus(eReturnStatusFailed);
2783 break;
2788 if (changed) {
2789 target->ModulesDidLoad(matching_modules);
2790 Process *process = m_exe_ctx.GetProcessPtr();
2791 if (process)
2792 process->Flush();
2794 if (load) {
2795 ProcessSP process = target->CalculateProcess();
2796 Address file_entry = objfile->GetEntryPointAddress();
2797 if (!process) {
2798 result.AppendError("No process");
2799 return false;
2801 if (set_pc && !file_entry.IsValid()) {
2802 result.AppendError("No entry address in object file");
2803 return false;
2805 std::vector<ObjectFile::LoadableData> loadables(
2806 objfile->GetLoadableData(*target));
2807 if (loadables.size() == 0) {
2808 result.AppendError("No loadable sections");
2809 return false;
2811 Status error = process->WriteObjectFile(std::move(loadables));
2812 if (error.Fail()) {
2813 result.AppendError(error.AsCString());
2814 return false;
2816 if (set_pc) {
2817 ThreadList &thread_list = process->GetThreadList();
2818 RegisterContextSP reg_context(
2819 thread_list.GetSelectedThread()->GetRegisterContext());
2820 addr_t file_entry_addr = file_entry.GetLoadAddress(target);
2821 if (!reg_context->SetPC(file_entry_addr)) {
2822 result.AppendErrorWithFormat("failed to set PC value to "
2823 "0x%" PRIx64 "\n",
2824 file_entry_addr);
2825 result.SetStatus(eReturnStatusFailed);
2829 } else {
2830 module->GetFileSpec().GetPath(path, sizeof(path));
2831 result.AppendErrorWithFormat("no sections in object file '%s'\n",
2832 path);
2833 result.SetStatus(eReturnStatusFailed);
2835 } else {
2836 module->GetFileSpec().GetPath(path, sizeof(path));
2837 result.AppendErrorWithFormat("no object file for module '%s'\n",
2838 path);
2839 result.SetStatus(eReturnStatusFailed);
2841 } else {
2842 FileSpec *module_spec_file = module_spec.GetFileSpecPtr();
2843 if (module_spec_file) {
2844 module_spec_file->GetPath(path, sizeof(path));
2845 result.AppendErrorWithFormat("invalid module '%s'.\n", path);
2846 } else
2847 result.AppendError("no module spec");
2848 result.SetStatus(eReturnStatusFailed);
2850 } else {
2851 std::string uuid_str;
2853 if (module_spec.GetFileSpec())
2854 module_spec.GetFileSpec().GetPath(path, sizeof(path));
2855 else
2856 path[0] = '\0';
2858 if (module_spec.GetUUIDPtr())
2859 uuid_str = module_spec.GetUUID().GetAsString();
2860 if (num_matches > 1) {
2861 result.AppendErrorWithFormat(
2862 "multiple modules match%s%s%s%s:\n", path[0] ? " file=" : "",
2863 path, !uuid_str.empty() ? " uuid=" : "", uuid_str.c_str());
2864 for (size_t i = 0; i < num_matches; ++i) {
2865 if (matching_modules.GetModulePointerAtIndex(i)
2866 ->GetFileSpec()
2867 .GetPath(path, sizeof(path)))
2868 result.AppendMessageWithFormat("%s\n", path);
2870 } else {
2871 result.AppendErrorWithFormat(
2872 "no modules were found that match%s%s%s%s.\n",
2873 path[0] ? " file=" : "", path, !uuid_str.empty() ? " uuid=" : "",
2874 uuid_str.c_str());
2876 result.SetStatus(eReturnStatusFailed);
2878 } else {
2879 result.AppendError("either the \"--file <module>\" or the \"--uuid "
2880 "<uuid>\" option must be specified.\n");
2881 result.SetStatus(eReturnStatusFailed);
2882 return false;
2884 return result.Succeeded();
2887 OptionGroupOptions m_option_group;
2888 OptionGroupUUID m_uuid_option_group;
2889 OptionGroupString m_file_option;
2890 OptionGroupBoolean m_load_option;
2891 OptionGroupBoolean m_pc_option;
2892 OptionGroupUInt64 m_slide_option;
2895 // List images with associated information
2896 #define LLDB_OPTIONS_target_modules_list
2897 #include "CommandOptions.inc"
2899 class CommandObjectTargetModulesList : public CommandObjectParsed {
2900 public:
2901 class CommandOptions : public Options {
2902 public:
2903 CommandOptions()
2904 : Options(), m_format_array(), m_use_global_module_list(false),
2905 m_module_addr(LLDB_INVALID_ADDRESS) {}
2907 ~CommandOptions() override = default;
2909 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2910 ExecutionContext *execution_context) override {
2911 Status error;
2913 const int short_option = m_getopt_table[option_idx].val;
2914 if (short_option == 'g') {
2915 m_use_global_module_list = true;
2916 } else if (short_option == 'a') {
2917 m_module_addr = OptionArgParser::ToAddress(
2918 execution_context, option_arg, LLDB_INVALID_ADDRESS, &error);
2919 } else {
2920 unsigned long width = 0;
2921 option_arg.getAsInteger(0, width);
2922 m_format_array.push_back(std::make_pair(short_option, width));
2924 return error;
2927 void OptionParsingStarting(ExecutionContext *execution_context) override {
2928 m_format_array.clear();
2929 m_use_global_module_list = false;
2930 m_module_addr = LLDB_INVALID_ADDRESS;
2933 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2934 return llvm::makeArrayRef(g_target_modules_list_options);
2937 // Instance variables to hold the values for command options.
2938 typedef std::vector<std::pair<char, uint32_t>> FormatWidthCollection;
2939 FormatWidthCollection m_format_array;
2940 bool m_use_global_module_list;
2941 lldb::addr_t m_module_addr;
2944 CommandObjectTargetModulesList(CommandInterpreter &interpreter)
2945 : CommandObjectParsed(
2946 interpreter, "target modules list",
2947 "List current executable and dependent shared library images.",
2948 "target modules list [<cmd-options>]"),
2949 m_options() {}
2951 ~CommandObjectTargetModulesList() override = default;
2953 Options *GetOptions() override { return &m_options; }
2955 protected:
2956 bool DoExecute(Args &command, CommandReturnObject &result) override {
2957 Target *target = GetDebugger().GetSelectedTarget().get();
2958 const bool use_global_module_list = m_options.m_use_global_module_list;
2959 // Define a local module list here to ensure it lives longer than any
2960 // "locker" object which might lock its contents below (through the
2961 // "module_list_ptr" variable).
2962 ModuleList module_list;
2963 if (target == nullptr && !use_global_module_list) {
2964 result.AppendError("invalid target, create a debug target using the "
2965 "'target create' command");
2966 result.SetStatus(eReturnStatusFailed);
2967 return false;
2968 } else {
2969 if (target) {
2970 uint32_t addr_byte_size =
2971 target->GetArchitecture().GetAddressByteSize();
2972 result.GetOutputStream().SetAddressByteSize(addr_byte_size);
2973 result.GetErrorStream().SetAddressByteSize(addr_byte_size);
2975 // Dump all sections for all modules images
2976 Stream &strm = result.GetOutputStream();
2978 if (m_options.m_module_addr != LLDB_INVALID_ADDRESS) {
2979 if (target) {
2980 Address module_address;
2981 if (module_address.SetLoadAddress(m_options.m_module_addr, target)) {
2982 ModuleSP module_sp(module_address.GetModule());
2983 if (module_sp) {
2984 PrintModule(target, module_sp.get(), 0, strm);
2985 result.SetStatus(eReturnStatusSuccessFinishResult);
2986 } else {
2987 result.AppendErrorWithFormat(
2988 "Couldn't find module matching address: 0x%" PRIx64 ".",
2989 m_options.m_module_addr);
2990 result.SetStatus(eReturnStatusFailed);
2992 } else {
2993 result.AppendErrorWithFormat(
2994 "Couldn't find module containing address: 0x%" PRIx64 ".",
2995 m_options.m_module_addr);
2996 result.SetStatus(eReturnStatusFailed);
2998 } else {
2999 result.AppendError(
3000 "Can only look up modules by address with a valid target.");
3001 result.SetStatus(eReturnStatusFailed);
3003 return result.Succeeded();
3006 size_t num_modules = 0;
3008 // This locker will be locked on the mutex in module_list_ptr if it is
3009 // non-nullptr. Otherwise it will lock the
3010 // AllocationModuleCollectionMutex when accessing the global module list
3011 // directly.
3012 std::unique_lock<std::recursive_mutex> guard(
3013 Module::GetAllocationModuleCollectionMutex(), std::defer_lock);
3015 const ModuleList *module_list_ptr = nullptr;
3016 const size_t argc = command.GetArgumentCount();
3017 if (argc == 0) {
3018 if (use_global_module_list) {
3019 guard.lock();
3020 num_modules = Module::GetNumberAllocatedModules();
3021 } else {
3022 module_list_ptr = &target->GetImages();
3024 } else {
3025 // TODO: Convert to entry based iteration. Requires converting
3026 // FindModulesByName.
3027 for (size_t i = 0; i < argc; ++i) {
3028 // Dump specified images (by basename or fullpath)
3029 const char *arg_cstr = command.GetArgumentAtIndex(i);
3030 const size_t num_matches = FindModulesByName(
3031 target, arg_cstr, module_list, use_global_module_list);
3032 if (num_matches == 0) {
3033 if (argc == 1) {
3034 result.AppendErrorWithFormat("no modules found that match '%s'",
3035 arg_cstr);
3036 result.SetStatus(eReturnStatusFailed);
3037 return false;
3042 module_list_ptr = &module_list;
3045 std::unique_lock<std::recursive_mutex> lock;
3046 if (module_list_ptr != nullptr) {
3047 lock =
3048 std::unique_lock<std::recursive_mutex>(module_list_ptr->GetMutex());
3050 num_modules = module_list_ptr->GetSize();
3053 if (num_modules > 0) {
3054 for (uint32_t image_idx = 0; image_idx < num_modules; ++image_idx) {
3055 ModuleSP module_sp;
3056 Module *module;
3057 if (module_list_ptr) {
3058 module_sp = module_list_ptr->GetModuleAtIndexUnlocked(image_idx);
3059 module = module_sp.get();
3060 } else {
3061 module = Module::GetAllocatedModuleAtIndex(image_idx);
3062 module_sp = module->shared_from_this();
3065 const size_t indent = strm.Printf("[%3u] ", image_idx);
3066 PrintModule(target, module, indent, strm);
3068 result.SetStatus(eReturnStatusSuccessFinishResult);
3069 } else {
3070 if (argc) {
3071 if (use_global_module_list)
3072 result.AppendError(
3073 "the global module list has no matching modules");
3074 else
3075 result.AppendError("the target has no matching modules");
3076 } else {
3077 if (use_global_module_list)
3078 result.AppendError("the global module list is empty");
3079 else
3080 result.AppendError(
3081 "the target has no associated executable images");
3083 result.SetStatus(eReturnStatusFailed);
3084 return false;
3087 return result.Succeeded();
3090 void PrintModule(Target *target, Module *module, int indent, Stream &strm) {
3091 if (module == nullptr) {
3092 strm.PutCString("Null module");
3093 return;
3096 bool dump_object_name = false;
3097 if (m_options.m_format_array.empty()) {
3098 m_options.m_format_array.push_back(std::make_pair('u', 0));
3099 m_options.m_format_array.push_back(std::make_pair('h', 0));
3100 m_options.m_format_array.push_back(std::make_pair('f', 0));
3101 m_options.m_format_array.push_back(std::make_pair('S', 0));
3103 const size_t num_entries = m_options.m_format_array.size();
3104 bool print_space = false;
3105 for (size_t i = 0; i < num_entries; ++i) {
3106 if (print_space)
3107 strm.PutChar(' ');
3108 print_space = true;
3109 const char format_char = m_options.m_format_array[i].first;
3110 uint32_t width = m_options.m_format_array[i].second;
3111 switch (format_char) {
3112 case 'A':
3113 DumpModuleArchitecture(strm, module, false, width);
3114 break;
3116 case 't':
3117 DumpModuleArchitecture(strm, module, true, width);
3118 break;
3120 case 'f':
3121 DumpFullpath(strm, &module->GetFileSpec(), width);
3122 dump_object_name = true;
3123 break;
3125 case 'd':
3126 DumpDirectory(strm, &module->GetFileSpec(), width);
3127 break;
3129 case 'b':
3130 DumpBasename(strm, &module->GetFileSpec(), width);
3131 dump_object_name = true;
3132 break;
3134 case 'h':
3135 case 'o':
3136 // Image header address
3138 uint32_t addr_nibble_width =
3139 target ? (target->GetArchitecture().GetAddressByteSize() * 2)
3140 : 16;
3142 ObjectFile *objfile = module->GetObjectFile();
3143 if (objfile) {
3144 Address base_addr(objfile->GetBaseAddress());
3145 if (base_addr.IsValid()) {
3146 if (target && !target->GetSectionLoadList().IsEmpty()) {
3147 lldb::addr_t load_addr = base_addr.GetLoadAddress(target);
3148 if (load_addr == LLDB_INVALID_ADDRESS) {
3149 base_addr.Dump(&strm, target,
3150 Address::DumpStyleModuleWithFileAddress,
3151 Address::DumpStyleFileAddress);
3152 } else {
3153 if (format_char == 'o') {
3154 // Show the offset of slide for the image
3155 strm.Printf("0x%*.*" PRIx64, addr_nibble_width,
3156 addr_nibble_width,
3157 load_addr - base_addr.GetFileAddress());
3158 } else {
3159 // Show the load address of the image
3160 strm.Printf("0x%*.*" PRIx64, addr_nibble_width,
3161 addr_nibble_width, load_addr);
3164 break;
3166 // The address was valid, but the image isn't loaded, output the
3167 // address in an appropriate format
3168 base_addr.Dump(&strm, target, Address::DumpStyleFileAddress);
3169 break;
3172 strm.Printf("%*s", addr_nibble_width + 2, "");
3174 break;
3176 case 'r': {
3177 size_t ref_count = 0;
3178 ModuleSP module_sp(module->shared_from_this());
3179 if (module_sp) {
3180 // Take one away to make sure we don't count our local "module_sp"
3181 ref_count = module_sp.use_count() - 1;
3183 if (width)
3184 strm.Printf("{%*" PRIu64 "}", width, (uint64_t)ref_count);
3185 else
3186 strm.Printf("{%" PRIu64 "}", (uint64_t)ref_count);
3187 } break;
3189 case 's':
3190 case 'S': {
3191 if (const SymbolFile *symbol_file = module->GetSymbolFile()) {
3192 const FileSpec symfile_spec =
3193 symbol_file->GetObjectFile()->GetFileSpec();
3194 if (format_char == 'S') {
3195 // Dump symbol file only if different from module file
3196 if (!symfile_spec || symfile_spec == module->GetFileSpec()) {
3197 print_space = false;
3198 break;
3200 // Add a newline and indent past the index
3201 strm.Printf("\n%*s", indent, "");
3203 DumpFullpath(strm, &symfile_spec, width);
3204 dump_object_name = true;
3205 break;
3207 strm.Printf("%.*s", width, "<NONE>");
3208 } break;
3210 case 'm':
3211 strm.Format("{0:%c}", llvm::fmt_align(module->GetModificationTime(),
3212 llvm::AlignStyle::Left, width));
3213 break;
3215 case 'p':
3216 strm.Printf("%p", static_cast<void *>(module));
3217 break;
3219 case 'u':
3220 DumpModuleUUID(strm, module);
3221 break;
3223 default:
3224 break;
3227 if (dump_object_name) {
3228 const char *object_name = module->GetObjectName().GetCString();
3229 if (object_name)
3230 strm.Printf("(%s)", object_name);
3232 strm.EOL();
3235 CommandOptions m_options;
3238 #pragma mark CommandObjectTargetModulesShowUnwind
3240 // Lookup unwind information in images
3241 #define LLDB_OPTIONS_target_modules_show_unwind
3242 #include "CommandOptions.inc"
3244 class CommandObjectTargetModulesShowUnwind : public CommandObjectParsed {
3245 public:
3246 enum {
3247 eLookupTypeInvalid = -1,
3248 eLookupTypeAddress = 0,
3249 eLookupTypeSymbol,
3250 eLookupTypeFunction,
3251 eLookupTypeFunctionOrSymbol,
3252 kNumLookupTypes
3255 class CommandOptions : public Options {
3256 public:
3257 CommandOptions()
3258 : Options(), m_type(eLookupTypeInvalid), m_str(),
3259 m_addr(LLDB_INVALID_ADDRESS) {}
3261 ~CommandOptions() override = default;
3263 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
3264 ExecutionContext *execution_context) override {
3265 Status error;
3267 const int short_option = m_getopt_table[option_idx].val;
3269 switch (short_option) {
3270 case 'a': {
3271 m_str = option_arg;
3272 m_type = eLookupTypeAddress;
3273 m_addr = OptionArgParser::ToAddress(execution_context, option_arg,
3274 LLDB_INVALID_ADDRESS, &error);
3275 if (m_addr == LLDB_INVALID_ADDRESS)
3276 error.SetErrorStringWithFormat("invalid address string '%s'",
3277 option_arg.str().c_str());
3278 break;
3281 case 'n':
3282 m_str = option_arg;
3283 m_type = eLookupTypeFunctionOrSymbol;
3284 break;
3286 default:
3287 llvm_unreachable("Unimplemented option");
3290 return error;
3293 void OptionParsingStarting(ExecutionContext *execution_context) override {
3294 m_type = eLookupTypeInvalid;
3295 m_str.clear();
3296 m_addr = LLDB_INVALID_ADDRESS;
3299 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
3300 return llvm::makeArrayRef(g_target_modules_show_unwind_options);
3303 // Instance variables to hold the values for command options.
3305 int m_type; // Should be a eLookupTypeXXX enum after parsing options
3306 std::string m_str; // Holds name lookup
3307 lldb::addr_t m_addr; // Holds the address to lookup
3310 CommandObjectTargetModulesShowUnwind(CommandInterpreter &interpreter)
3311 : CommandObjectParsed(
3312 interpreter, "target modules show-unwind",
3313 "Show synthesized unwind instructions for a function.", nullptr,
3314 eCommandRequiresTarget | eCommandRequiresProcess |
3315 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused),
3316 m_options() {}
3318 ~CommandObjectTargetModulesShowUnwind() override = default;
3320 Options *GetOptions() override { return &m_options; }
3322 protected:
3323 bool DoExecute(Args &command, CommandReturnObject &result) override {
3324 Target *target = m_exe_ctx.GetTargetPtr();
3325 Process *process = m_exe_ctx.GetProcessPtr();
3326 ABI *abi = nullptr;
3327 if (process)
3328 abi = process->GetABI().get();
3330 if (process == nullptr) {
3331 result.AppendError(
3332 "You must have a process running to use this command.");
3333 result.SetStatus(eReturnStatusFailed);
3334 return false;
3337 ThreadList threads(process->GetThreadList());
3338 if (threads.GetSize() == 0) {
3339 result.AppendError("The process must be paused to use this command.");
3340 result.SetStatus(eReturnStatusFailed);
3341 return false;
3344 ThreadSP thread(threads.GetThreadAtIndex(0));
3345 if (!thread) {
3346 result.AppendError("The process must be paused to use this command.");
3347 result.SetStatus(eReturnStatusFailed);
3348 return false;
3351 SymbolContextList sc_list;
3353 if (m_options.m_type == eLookupTypeFunctionOrSymbol) {
3354 ConstString function_name(m_options.m_str.c_str());
3355 target->GetImages().FindFunctions(function_name, eFunctionNameTypeAuto,
3356 true, false, sc_list);
3357 } else if (m_options.m_type == eLookupTypeAddress && target) {
3358 Address addr;
3359 if (target->GetSectionLoadList().ResolveLoadAddress(m_options.m_addr,
3360 addr)) {
3361 SymbolContext sc;
3362 ModuleSP module_sp(addr.GetModule());
3363 module_sp->ResolveSymbolContextForAddress(addr,
3364 eSymbolContextEverything, sc);
3365 if (sc.function || sc.symbol) {
3366 sc_list.Append(sc);
3369 } else {
3370 result.AppendError(
3371 "address-expression or function name option must be specified.");
3372 result.SetStatus(eReturnStatusFailed);
3373 return false;
3376 size_t num_matches = sc_list.GetSize();
3377 if (num_matches == 0) {
3378 result.AppendErrorWithFormat("no unwind data found that matches '%s'.",
3379 m_options.m_str.c_str());
3380 result.SetStatus(eReturnStatusFailed);
3381 return false;
3384 for (uint32_t idx = 0; idx < num_matches; idx++) {
3385 SymbolContext sc;
3386 sc_list.GetContextAtIndex(idx, sc);
3387 if (sc.symbol == nullptr && sc.function == nullptr)
3388 continue;
3389 if (!sc.module_sp || sc.module_sp->GetObjectFile() == nullptr)
3390 continue;
3391 AddressRange range;
3392 if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0,
3393 false, range))
3394 continue;
3395 if (!range.GetBaseAddress().IsValid())
3396 continue;
3397 ConstString funcname(sc.GetFunctionName());
3398 if (funcname.IsEmpty())
3399 continue;
3400 addr_t start_addr = range.GetBaseAddress().GetLoadAddress(target);
3401 if (abi)
3402 start_addr = abi->FixCodeAddress(start_addr);
3404 FuncUnwindersSP func_unwinders_sp(
3405 sc.module_sp->GetUnwindTable()
3406 .GetUncachedFuncUnwindersContainingAddress(start_addr, sc));
3407 if (!func_unwinders_sp)
3408 continue;
3410 result.GetOutputStream().Printf(
3411 "UNWIND PLANS for %s`%s (start addr 0x%" PRIx64 ")\n\n",
3412 sc.module_sp->GetPlatformFileSpec().GetFilename().AsCString(),
3413 funcname.AsCString(), start_addr);
3415 UnwindPlanSP non_callsite_unwind_plan =
3416 func_unwinders_sp->GetUnwindPlanAtNonCallSite(*target, *thread);
3417 if (non_callsite_unwind_plan) {
3418 result.GetOutputStream().Printf(
3419 "Asynchronous (not restricted to call-sites) UnwindPlan is '%s'\n",
3420 non_callsite_unwind_plan->GetSourceName().AsCString());
3422 UnwindPlanSP callsite_unwind_plan =
3423 func_unwinders_sp->GetUnwindPlanAtCallSite(*target, *thread);
3424 if (callsite_unwind_plan) {
3425 result.GetOutputStream().Printf(
3426 "Synchronous (restricted to call-sites) UnwindPlan is '%s'\n",
3427 callsite_unwind_plan->GetSourceName().AsCString());
3429 UnwindPlanSP fast_unwind_plan =
3430 func_unwinders_sp->GetUnwindPlanFastUnwind(*target, *thread);
3431 if (fast_unwind_plan) {
3432 result.GetOutputStream().Printf(
3433 "Fast UnwindPlan is '%s'\n",
3434 fast_unwind_plan->GetSourceName().AsCString());
3437 result.GetOutputStream().Printf("\n");
3439 UnwindPlanSP assembly_sp =
3440 func_unwinders_sp->GetAssemblyUnwindPlan(*target, *thread);
3441 if (assembly_sp) {
3442 result.GetOutputStream().Printf(
3443 "Assembly language inspection UnwindPlan:\n");
3444 assembly_sp->Dump(result.GetOutputStream(), thread.get(),
3445 LLDB_INVALID_ADDRESS);
3446 result.GetOutputStream().Printf("\n");
3449 UnwindPlanSP of_unwind_sp =
3450 func_unwinders_sp->GetObjectFileUnwindPlan(*target);
3451 if (of_unwind_sp) {
3452 result.GetOutputStream().Printf("object file UnwindPlan:\n");
3453 of_unwind_sp->Dump(result.GetOutputStream(), thread.get(),
3454 LLDB_INVALID_ADDRESS);
3455 result.GetOutputStream().Printf("\n");
3458 UnwindPlanSP of_unwind_augmented_sp =
3459 func_unwinders_sp->GetObjectFileAugmentedUnwindPlan(*target, *thread);
3460 if (of_unwind_augmented_sp) {
3461 result.GetOutputStream().Printf("object file augmented UnwindPlan:\n");
3462 of_unwind_augmented_sp->Dump(result.GetOutputStream(), thread.get(),
3463 LLDB_INVALID_ADDRESS);
3464 result.GetOutputStream().Printf("\n");
3467 UnwindPlanSP ehframe_sp =
3468 func_unwinders_sp->GetEHFrameUnwindPlan(*target);
3469 if (ehframe_sp) {
3470 result.GetOutputStream().Printf("eh_frame UnwindPlan:\n");
3471 ehframe_sp->Dump(result.GetOutputStream(), thread.get(),
3472 LLDB_INVALID_ADDRESS);
3473 result.GetOutputStream().Printf("\n");
3476 UnwindPlanSP ehframe_augmented_sp =
3477 func_unwinders_sp->GetEHFrameAugmentedUnwindPlan(*target, *thread);
3478 if (ehframe_augmented_sp) {
3479 result.GetOutputStream().Printf("eh_frame augmented UnwindPlan:\n");
3480 ehframe_augmented_sp->Dump(result.GetOutputStream(), thread.get(),
3481 LLDB_INVALID_ADDRESS);
3482 result.GetOutputStream().Printf("\n");
3485 if (UnwindPlanSP plan_sp =
3486 func_unwinders_sp->GetDebugFrameUnwindPlan(*target)) {
3487 result.GetOutputStream().Printf("debug_frame UnwindPlan:\n");
3488 plan_sp->Dump(result.GetOutputStream(), thread.get(),
3489 LLDB_INVALID_ADDRESS);
3490 result.GetOutputStream().Printf("\n");
3493 if (UnwindPlanSP plan_sp =
3494 func_unwinders_sp->GetDebugFrameAugmentedUnwindPlan(*target,
3495 *thread)) {
3496 result.GetOutputStream().Printf("debug_frame augmented UnwindPlan:\n");
3497 plan_sp->Dump(result.GetOutputStream(), thread.get(),
3498 LLDB_INVALID_ADDRESS);
3499 result.GetOutputStream().Printf("\n");
3502 UnwindPlanSP arm_unwind_sp =
3503 func_unwinders_sp->GetArmUnwindUnwindPlan(*target);
3504 if (arm_unwind_sp) {
3505 result.GetOutputStream().Printf("ARM.exidx unwind UnwindPlan:\n");
3506 arm_unwind_sp->Dump(result.GetOutputStream(), thread.get(),
3507 LLDB_INVALID_ADDRESS);
3508 result.GetOutputStream().Printf("\n");
3511 if (UnwindPlanSP symfile_plan_sp =
3512 func_unwinders_sp->GetSymbolFileUnwindPlan(*thread)) {
3513 result.GetOutputStream().Printf("Symbol file UnwindPlan:\n");
3514 symfile_plan_sp->Dump(result.GetOutputStream(), thread.get(),
3515 LLDB_INVALID_ADDRESS);
3516 result.GetOutputStream().Printf("\n");
3519 UnwindPlanSP compact_unwind_sp =
3520 func_unwinders_sp->GetCompactUnwindUnwindPlan(*target);
3521 if (compact_unwind_sp) {
3522 result.GetOutputStream().Printf("Compact unwind UnwindPlan:\n");
3523 compact_unwind_sp->Dump(result.GetOutputStream(), thread.get(),
3524 LLDB_INVALID_ADDRESS);
3525 result.GetOutputStream().Printf("\n");
3528 if (fast_unwind_plan) {
3529 result.GetOutputStream().Printf("Fast UnwindPlan:\n");
3530 fast_unwind_plan->Dump(result.GetOutputStream(), thread.get(),
3531 LLDB_INVALID_ADDRESS);
3532 result.GetOutputStream().Printf("\n");
3535 ABISP abi_sp = process->GetABI();
3536 if (abi_sp) {
3537 UnwindPlan arch_default(lldb::eRegisterKindGeneric);
3538 if (abi_sp->CreateDefaultUnwindPlan(arch_default)) {
3539 result.GetOutputStream().Printf("Arch default UnwindPlan:\n");
3540 arch_default.Dump(result.GetOutputStream(), thread.get(),
3541 LLDB_INVALID_ADDRESS);
3542 result.GetOutputStream().Printf("\n");
3545 UnwindPlan arch_entry(lldb::eRegisterKindGeneric);
3546 if (abi_sp->CreateFunctionEntryUnwindPlan(arch_entry)) {
3547 result.GetOutputStream().Printf(
3548 "Arch default at entry point UnwindPlan:\n");
3549 arch_entry.Dump(result.GetOutputStream(), thread.get(),
3550 LLDB_INVALID_ADDRESS);
3551 result.GetOutputStream().Printf("\n");
3555 result.GetOutputStream().Printf("\n");
3557 return result.Succeeded();
3560 CommandOptions m_options;
3563 // Lookup information in images
3564 #define LLDB_OPTIONS_target_modules_lookup
3565 #include "CommandOptions.inc"
3567 class CommandObjectTargetModulesLookup : public CommandObjectParsed {
3568 public:
3569 enum {
3570 eLookupTypeInvalid = -1,
3571 eLookupTypeAddress = 0,
3572 eLookupTypeSymbol,
3573 eLookupTypeFileLine, // Line is optional
3574 eLookupTypeFunction,
3575 eLookupTypeFunctionOrSymbol,
3576 eLookupTypeType,
3577 kNumLookupTypes
3580 class CommandOptions : public Options {
3581 public:
3582 CommandOptions() : Options() { OptionParsingStarting(nullptr); }
3584 ~CommandOptions() override = default;
3586 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
3587 ExecutionContext *execution_context) override {
3588 Status error;
3590 const int short_option = m_getopt_table[option_idx].val;
3592 switch (short_option) {
3593 case 'a': {
3594 m_type = eLookupTypeAddress;
3595 m_addr = OptionArgParser::ToAddress(execution_context, option_arg,
3596 LLDB_INVALID_ADDRESS, &error);
3597 } break;
3599 case 'o':
3600 if (option_arg.getAsInteger(0, m_offset))
3601 error.SetErrorStringWithFormat("invalid offset string '%s'",
3602 option_arg.str().c_str());
3603 break;
3605 case 's':
3606 m_str = option_arg;
3607 m_type = eLookupTypeSymbol;
3608 break;
3610 case 'f':
3611 m_file.SetFile(option_arg, FileSpec::Style::native);
3612 m_type = eLookupTypeFileLine;
3613 break;
3615 case 'i':
3616 m_include_inlines = false;
3617 break;
3619 case 'l':
3620 if (option_arg.getAsInteger(0, m_line_number))
3621 error.SetErrorStringWithFormat("invalid line number string '%s'",
3622 option_arg.str().c_str());
3623 else if (m_line_number == 0)
3624 error.SetErrorString("zero is an invalid line number");
3625 m_type = eLookupTypeFileLine;
3626 break;
3628 case 'F':
3629 m_str = option_arg;
3630 m_type = eLookupTypeFunction;
3631 break;
3633 case 'n':
3634 m_str = option_arg;
3635 m_type = eLookupTypeFunctionOrSymbol;
3636 break;
3638 case 't':
3639 m_str = option_arg;
3640 m_type = eLookupTypeType;
3641 break;
3643 case 'v':
3644 m_verbose = true;
3645 break;
3647 case 'A':
3648 m_print_all = true;
3649 break;
3651 case 'r':
3652 m_use_regex = true;
3653 break;
3654 default:
3655 llvm_unreachable("Unimplemented option");
3658 return error;
3661 void OptionParsingStarting(ExecutionContext *execution_context) override {
3662 m_type = eLookupTypeInvalid;
3663 m_str.clear();
3664 m_file.Clear();
3665 m_addr = LLDB_INVALID_ADDRESS;
3666 m_offset = 0;
3667 m_line_number = 0;
3668 m_use_regex = false;
3669 m_include_inlines = true;
3670 m_verbose = false;
3671 m_print_all = false;
3674 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
3675 return llvm::makeArrayRef(g_target_modules_lookup_options);
3678 int m_type; // Should be a eLookupTypeXXX enum after parsing options
3679 std::string m_str; // Holds name lookup
3680 FileSpec m_file; // Files for file lookups
3681 lldb::addr_t m_addr; // Holds the address to lookup
3682 lldb::addr_t
3683 m_offset; // Subtract this offset from m_addr before doing lookups.
3684 uint32_t m_line_number; // Line number for file+line lookups
3685 bool m_use_regex; // Name lookups in m_str are regular expressions.
3686 bool m_include_inlines; // Check for inline entries when looking up by
3687 // file/line.
3688 bool m_verbose; // Enable verbose lookup info
3689 bool m_print_all; // Print all matches, even in cases where there's a best
3690 // match.
3693 CommandObjectTargetModulesLookup(CommandInterpreter &interpreter)
3694 : CommandObjectParsed(interpreter, "target modules lookup",
3695 "Look up information within executable and "
3696 "dependent shared library images.",
3697 nullptr, eCommandRequiresTarget),
3698 m_options() {
3699 CommandArgumentEntry arg;
3700 CommandArgumentData file_arg;
3702 // Define the first (and only) variant of this arg.
3703 file_arg.arg_type = eArgTypeFilename;
3704 file_arg.arg_repetition = eArgRepeatStar;
3706 // There is only one variant this argument could be; put it into the
3707 // argument entry.
3708 arg.push_back(file_arg);
3710 // Push the data for the first argument into the m_arguments vector.
3711 m_arguments.push_back(arg);
3714 ~CommandObjectTargetModulesLookup() override = default;
3716 Options *GetOptions() override { return &m_options; }
3718 bool LookupHere(CommandInterpreter &interpreter, CommandReturnObject &result,
3719 bool &syntax_error) {
3720 switch (m_options.m_type) {
3721 case eLookupTypeAddress:
3722 case eLookupTypeFileLine:
3723 case eLookupTypeFunction:
3724 case eLookupTypeFunctionOrSymbol:
3725 case eLookupTypeSymbol:
3726 default:
3727 return false;
3728 case eLookupTypeType:
3729 break;
3732 StackFrameSP frame = m_exe_ctx.GetFrameSP();
3734 if (!frame)
3735 return false;
3737 const SymbolContext &sym_ctx(frame->GetSymbolContext(eSymbolContextModule));
3739 if (!sym_ctx.module_sp)
3740 return false;
3742 switch (m_options.m_type) {
3743 default:
3744 return false;
3745 case eLookupTypeType:
3746 if (!m_options.m_str.empty()) {
3747 if (LookupTypeHere(m_interpreter, result.GetOutputStream(),
3748 *sym_ctx.module_sp, m_options.m_str.c_str(),
3749 m_options.m_use_regex)) {
3750 result.SetStatus(eReturnStatusSuccessFinishResult);
3751 return true;
3754 break;
3757 return false;
3760 bool LookupInModule(CommandInterpreter &interpreter, Module *module,
3761 CommandReturnObject &result, bool &syntax_error) {
3762 switch (m_options.m_type) {
3763 case eLookupTypeAddress:
3764 if (m_options.m_addr != LLDB_INVALID_ADDRESS) {
3765 if (LookupAddressInModule(
3766 m_interpreter, result.GetOutputStream(), module,
3767 eSymbolContextEverything |
3768 (m_options.m_verbose
3769 ? static_cast<int>(eSymbolContextVariable)
3770 : 0),
3771 m_options.m_addr, m_options.m_offset, m_options.m_verbose)) {
3772 result.SetStatus(eReturnStatusSuccessFinishResult);
3773 return true;
3776 break;
3778 case eLookupTypeSymbol:
3779 if (!m_options.m_str.empty()) {
3780 if (LookupSymbolInModule(m_interpreter, result.GetOutputStream(),
3781 module, m_options.m_str.c_str(),
3782 m_options.m_use_regex, m_options.m_verbose)) {
3783 result.SetStatus(eReturnStatusSuccessFinishResult);
3784 return true;
3787 break;
3789 case eLookupTypeFileLine:
3790 if (m_options.m_file) {
3791 if (LookupFileAndLineInModule(
3792 m_interpreter, result.GetOutputStream(), module,
3793 m_options.m_file, m_options.m_line_number,
3794 m_options.m_include_inlines, m_options.m_verbose)) {
3795 result.SetStatus(eReturnStatusSuccessFinishResult);
3796 return true;
3799 break;
3801 case eLookupTypeFunctionOrSymbol:
3802 case eLookupTypeFunction:
3803 if (!m_options.m_str.empty()) {
3804 if (LookupFunctionInModule(
3805 m_interpreter, result.GetOutputStream(), module,
3806 m_options.m_str.c_str(), m_options.m_use_regex,
3807 m_options.m_include_inlines,
3808 m_options.m_type ==
3809 eLookupTypeFunctionOrSymbol, // include symbols
3810 m_options.m_verbose)) {
3811 result.SetStatus(eReturnStatusSuccessFinishResult);
3812 return true;
3815 break;
3817 case eLookupTypeType:
3818 if (!m_options.m_str.empty()) {
3819 if (LookupTypeInModule(m_interpreter, result.GetOutputStream(), module,
3820 m_options.m_str.c_str(),
3821 m_options.m_use_regex)) {
3822 result.SetStatus(eReturnStatusSuccessFinishResult);
3823 return true;
3826 break;
3828 default:
3829 m_options.GenerateOptionUsage(
3830 result.GetErrorStream(), this,
3831 GetCommandInterpreter().GetDebugger().GetTerminalWidth());
3832 syntax_error = true;
3833 break;
3836 result.SetStatus(eReturnStatusFailed);
3837 return false;
3840 protected:
3841 bool DoExecute(Args &command, CommandReturnObject &result) override {
3842 Target *target = &GetSelectedTarget();
3843 bool syntax_error = false;
3844 uint32_t i;
3845 uint32_t num_successful_lookups = 0;
3846 uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
3847 result.GetOutputStream().SetAddressByteSize(addr_byte_size);
3848 result.GetErrorStream().SetAddressByteSize(addr_byte_size);
3849 // Dump all sections for all modules images
3851 if (command.GetArgumentCount() == 0) {
3852 ModuleSP current_module;
3854 // Where it is possible to look in the current symbol context first,
3855 // try that. If this search was successful and --all was not passed,
3856 // don't print anything else.
3857 if (LookupHere(m_interpreter, result, syntax_error)) {
3858 result.GetOutputStream().EOL();
3859 num_successful_lookups++;
3860 if (!m_options.m_print_all) {
3861 result.SetStatus(eReturnStatusSuccessFinishResult);
3862 return result.Succeeded();
3866 // Dump all sections for all other modules
3868 const ModuleList &target_modules = target->GetImages();
3869 std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
3870 const size_t num_modules = target_modules.GetSize();
3871 if (num_modules > 0) {
3872 for (i = 0; i < num_modules && !syntax_error; ++i) {
3873 Module *module_pointer =
3874 target_modules.GetModulePointerAtIndexUnlocked(i);
3876 if (module_pointer != current_module.get() &&
3877 LookupInModule(m_interpreter,
3878 target_modules.GetModulePointerAtIndexUnlocked(i),
3879 result, syntax_error)) {
3880 result.GetOutputStream().EOL();
3881 num_successful_lookups++;
3884 } else {
3885 result.AppendError("the target has no associated executable images");
3886 result.SetStatus(eReturnStatusFailed);
3887 return false;
3889 } else {
3890 // Dump specified images (by basename or fullpath)
3891 const char *arg_cstr;
3892 for (i = 0; (arg_cstr = command.GetArgumentAtIndex(i)) != nullptr &&
3893 !syntax_error;
3894 ++i) {
3895 ModuleList module_list;
3896 const size_t num_matches =
3897 FindModulesByName(target, arg_cstr, module_list, false);
3898 if (num_matches > 0) {
3899 for (size_t j = 0; j < num_matches; ++j) {
3900 Module *module = module_list.GetModulePointerAtIndex(j);
3901 if (module) {
3902 if (LookupInModule(m_interpreter, module, result, syntax_error)) {
3903 result.GetOutputStream().EOL();
3904 num_successful_lookups++;
3908 } else
3909 result.AppendWarningWithFormat(
3910 "Unable to find an image that matches '%s'.\n", arg_cstr);
3914 if (num_successful_lookups > 0)
3915 result.SetStatus(eReturnStatusSuccessFinishResult);
3916 else
3917 result.SetStatus(eReturnStatusFailed);
3918 return result.Succeeded();
3921 CommandOptions m_options;
3924 #pragma mark CommandObjectMultiwordImageSearchPaths
3926 // CommandObjectMultiwordImageSearchPaths
3928 class CommandObjectTargetModulesImageSearchPaths
3929 : public CommandObjectMultiword {
3930 public:
3931 CommandObjectTargetModulesImageSearchPaths(CommandInterpreter &interpreter)
3932 : CommandObjectMultiword(
3933 interpreter, "target modules search-paths",
3934 "Commands for managing module search paths for a target.",
3935 "target modules search-paths <subcommand> [<subcommand-options>]") {
3936 LoadSubCommand(
3937 "add", CommandObjectSP(
3938 new CommandObjectTargetModulesSearchPathsAdd(interpreter)));
3939 LoadSubCommand(
3940 "clear", CommandObjectSP(new CommandObjectTargetModulesSearchPathsClear(
3941 interpreter)));
3942 LoadSubCommand(
3943 "insert",
3944 CommandObjectSP(
3945 new CommandObjectTargetModulesSearchPathsInsert(interpreter)));
3946 LoadSubCommand(
3947 "list", CommandObjectSP(new CommandObjectTargetModulesSearchPathsList(
3948 interpreter)));
3949 LoadSubCommand(
3950 "query", CommandObjectSP(new CommandObjectTargetModulesSearchPathsQuery(
3951 interpreter)));
3954 ~CommandObjectTargetModulesImageSearchPaths() override = default;
3957 #pragma mark CommandObjectTargetModules
3959 // CommandObjectTargetModules
3961 class CommandObjectTargetModules : public CommandObjectMultiword {
3962 public:
3963 // Constructors and Destructors
3964 CommandObjectTargetModules(CommandInterpreter &interpreter)
3965 : CommandObjectMultiword(interpreter, "target modules",
3966 "Commands for accessing information for one or "
3967 "more target modules.",
3968 "target modules <sub-command> ...") {
3969 LoadSubCommand(
3970 "add", CommandObjectSP(new CommandObjectTargetModulesAdd(interpreter)));
3971 LoadSubCommand("load", CommandObjectSP(new CommandObjectTargetModulesLoad(
3972 interpreter)));
3973 LoadSubCommand("dump", CommandObjectSP(new CommandObjectTargetModulesDump(
3974 interpreter)));
3975 LoadSubCommand("list", CommandObjectSP(new CommandObjectTargetModulesList(
3976 interpreter)));
3977 LoadSubCommand(
3978 "lookup",
3979 CommandObjectSP(new CommandObjectTargetModulesLookup(interpreter)));
3980 LoadSubCommand(
3981 "search-paths",
3982 CommandObjectSP(
3983 new CommandObjectTargetModulesImageSearchPaths(interpreter)));
3984 LoadSubCommand(
3985 "show-unwind",
3986 CommandObjectSP(new CommandObjectTargetModulesShowUnwind(interpreter)));
3989 ~CommandObjectTargetModules() override = default;
3991 private:
3992 // For CommandObjectTargetModules only
3993 DISALLOW_COPY_AND_ASSIGN(CommandObjectTargetModules);
3996 class CommandObjectTargetSymbolsAdd : public CommandObjectParsed {
3997 public:
3998 CommandObjectTargetSymbolsAdd(CommandInterpreter &interpreter)
3999 : CommandObjectParsed(
4000 interpreter, "target symbols add",
4001 "Add a debug symbol file to one of the target's current modules by "
4002 "specifying a path to a debug symbols file, or using the options "
4003 "to specify a module to download symbols for.",
4004 "target symbols add <cmd-options> [<symfile>]",
4005 eCommandRequiresTarget),
4006 m_option_group(),
4007 m_file_option(
4008 LLDB_OPT_SET_1, false, "shlib", 's',
4009 CommandCompletions::eModuleCompletion, eArgTypeShlibName,
4010 "Fullpath or basename for module to find debug symbols for."),
4011 m_current_frame_option(
4012 LLDB_OPT_SET_2, false, "frame", 'F',
4013 "Locate the debug symbols the currently selected frame.", false,
4014 true)
4017 m_option_group.Append(&m_uuid_option_group, LLDB_OPT_SET_ALL,
4018 LLDB_OPT_SET_1);
4019 m_option_group.Append(&m_file_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
4020 m_option_group.Append(&m_current_frame_option, LLDB_OPT_SET_2,
4021 LLDB_OPT_SET_2);
4022 m_option_group.Finalize();
4025 ~CommandObjectTargetSymbolsAdd() override = default;
4027 void
4028 HandleArgumentCompletion(CompletionRequest &request,
4029 OptionElementVector &opt_element_vector) override {
4030 CommandCompletions::InvokeCommonCompletionCallbacks(
4031 GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
4032 request, nullptr);
4035 Options *GetOptions() override { return &m_option_group; }
4037 protected:
4038 bool AddModuleSymbols(Target *target, ModuleSpec &module_spec, bool &flush,
4039 CommandReturnObject &result) {
4040 const FileSpec &symbol_fspec = module_spec.GetSymbolFileSpec();
4041 if (!symbol_fspec) {
4042 result.AppendError(
4043 "one or more executable image paths must be specified");
4044 result.SetStatus(eReturnStatusFailed);
4045 return false;
4048 char symfile_path[PATH_MAX];
4049 symbol_fspec.GetPath(symfile_path, sizeof(symfile_path));
4051 if (!module_spec.GetUUID().IsValid()) {
4052 if (!module_spec.GetFileSpec() && !module_spec.GetPlatformFileSpec())
4053 module_spec.GetFileSpec().GetFilename() = symbol_fspec.GetFilename();
4056 // We now have a module that represents a symbol file that can be used
4057 // for a module that might exist in the current target, so we need to
4058 // find that module in the target
4059 ModuleList matching_module_list;
4061 size_t num_matches = 0;
4062 // First extract all module specs from the symbol file
4063 lldb_private::ModuleSpecList symfile_module_specs;
4064 if (ObjectFile::GetModuleSpecifications(module_spec.GetSymbolFileSpec(),
4065 0, 0, symfile_module_specs)) {
4066 // Now extract the module spec that matches the target architecture
4067 ModuleSpec target_arch_module_spec;
4068 ModuleSpec symfile_module_spec;
4069 target_arch_module_spec.GetArchitecture() = target->GetArchitecture();
4070 if (symfile_module_specs.FindMatchingModuleSpec(target_arch_module_spec,
4071 symfile_module_spec)) {
4072 // See if it has a UUID?
4073 if (symfile_module_spec.GetUUID().IsValid()) {
4074 // It has a UUID, look for this UUID in the target modules
4075 ModuleSpec symfile_uuid_module_spec;
4076 symfile_uuid_module_spec.GetUUID() = symfile_module_spec.GetUUID();
4077 target->GetImages().FindModules(symfile_uuid_module_spec,
4078 matching_module_list);
4079 num_matches = matching_module_list.GetSize();
4083 if (num_matches == 0) {
4084 // No matches yet, iterate through the module specs to find a UUID
4085 // value that we can match up to an image in our target
4086 const size_t num_symfile_module_specs =
4087 symfile_module_specs.GetSize();
4088 for (size_t i = 0; i < num_symfile_module_specs && num_matches == 0;
4089 ++i) {
4090 if (symfile_module_specs.GetModuleSpecAtIndex(
4091 i, symfile_module_spec)) {
4092 if (symfile_module_spec.GetUUID().IsValid()) {
4093 // It has a UUID, look for this UUID in the target modules
4094 ModuleSpec symfile_uuid_module_spec;
4095 symfile_uuid_module_spec.GetUUID() =
4096 symfile_module_spec.GetUUID();
4097 target->GetImages().FindModules(symfile_uuid_module_spec,
4098 matching_module_list);
4099 num_matches = matching_module_list.GetSize();
4106 // Just try to match up the file by basename if we have no matches at
4107 // this point
4108 if (num_matches == 0) {
4109 target->GetImages().FindModules(module_spec, matching_module_list);
4110 num_matches = matching_module_list.GetSize();
4113 while (num_matches == 0) {
4114 ConstString filename_no_extension(
4115 module_spec.GetFileSpec().GetFileNameStrippingExtension());
4116 // Empty string returned, let's bail
4117 if (!filename_no_extension)
4118 break;
4120 // Check if there was no extension to strip and the basename is the same
4121 if (filename_no_extension == module_spec.GetFileSpec().GetFilename())
4122 break;
4124 // Replace basename with one fewer extension
4125 module_spec.GetFileSpec().GetFilename() = filename_no_extension;
4126 target->GetImages().FindModules(module_spec, matching_module_list);
4127 num_matches = matching_module_list.GetSize();
4130 if (num_matches > 1) {
4131 result.AppendErrorWithFormat("multiple modules match symbol file '%s', "
4132 "use the --uuid option to resolve the "
4133 "ambiguity.\n",
4134 symfile_path);
4135 } else if (num_matches == 1) {
4136 ModuleSP module_sp(matching_module_list.GetModuleAtIndex(0));
4138 // The module has not yet created its symbol vendor, we can just give
4139 // the existing target module the symfile path to use for when it
4140 // decides to create it!
4141 module_sp->SetSymbolFileFileSpec(symbol_fspec);
4143 SymbolFile *symbol_file =
4144 module_sp->GetSymbolFile(true, &result.GetErrorStream());
4145 if (symbol_file) {
4146 ObjectFile *object_file = symbol_file->GetObjectFile();
4148 if (object_file && object_file->GetFileSpec() == symbol_fspec) {
4149 // Provide feedback that the symfile has been successfully added.
4150 const FileSpec &module_fs = module_sp->GetFileSpec();
4151 result.AppendMessageWithFormat(
4152 "symbol file '%s' has been added to '%s'\n", symfile_path,
4153 module_fs.GetPath().c_str());
4155 // Let clients know something changed in the module if it is
4156 // currently loaded
4157 ModuleList module_list;
4158 module_list.Append(module_sp);
4159 target->SymbolsDidLoad(module_list);
4161 // Make sure we load any scripting resources that may be embedded
4162 // in the debug info files in case the platform supports that.
4163 Status error;
4164 StreamString feedback_stream;
4165 module_sp->LoadScriptingResourceInTarget(target, error,
4166 &feedback_stream);
4167 if (error.Fail() && error.AsCString())
4168 result.AppendWarningWithFormat(
4169 "unable to load scripting data for module %s - error "
4170 "reported was %s",
4171 module_sp->GetFileSpec()
4172 .GetFileNameStrippingExtension()
4173 .GetCString(),
4174 error.AsCString());
4175 else if (feedback_stream.GetSize())
4176 result.AppendWarningWithFormat("%s", feedback_stream.GetData());
4178 flush = true;
4179 result.SetStatus(eReturnStatusSuccessFinishResult);
4180 return true;
4183 // Clear the symbol file spec if anything went wrong
4184 module_sp->SetSymbolFileFileSpec(FileSpec());
4187 namespace fs = llvm::sys::fs;
4188 StreamString ss_symfile_uuid;
4189 if (module_spec.GetUUID().IsValid()) {
4190 ss_symfile_uuid << " (";
4191 module_spec.GetUUID().Dump(&ss_symfile_uuid);
4192 ss_symfile_uuid << ')';
4194 result.AppendErrorWithFormat(
4195 "symbol file '%s'%s does not match any existing module%s\n",
4196 symfile_path, ss_symfile_uuid.GetData(),
4197 !fs::is_regular_file(symbol_fspec.GetPath())
4198 ? "\n please specify the full path to the symbol file"
4199 : "");
4200 result.SetStatus(eReturnStatusFailed);
4201 return false;
4204 bool DoExecute(Args &args, CommandReturnObject &result) override {
4205 Target *target = m_exe_ctx.GetTargetPtr();
4206 result.SetStatus(eReturnStatusFailed);
4207 bool flush = false;
4208 ModuleSpec module_spec;
4209 const bool uuid_option_set =
4210 m_uuid_option_group.GetOptionValue().OptionWasSet();
4211 const bool file_option_set = m_file_option.GetOptionValue().OptionWasSet();
4212 const bool frame_option_set =
4213 m_current_frame_option.GetOptionValue().OptionWasSet();
4214 const size_t argc = args.GetArgumentCount();
4216 if (argc == 0) {
4217 if (uuid_option_set || file_option_set || frame_option_set) {
4218 bool success = false;
4219 bool error_set = false;
4220 if (frame_option_set) {
4221 Process *process = m_exe_ctx.GetProcessPtr();
4222 if (process) {
4223 const StateType process_state = process->GetState();
4224 if (StateIsStoppedState(process_state, true)) {
4225 StackFrame *frame = m_exe_ctx.GetFramePtr();
4226 if (frame) {
4227 ModuleSP frame_module_sp(
4228 frame->GetSymbolContext(eSymbolContextModule).module_sp);
4229 if (frame_module_sp) {
4230 if (FileSystem::Instance().Exists(
4231 frame_module_sp->GetPlatformFileSpec())) {
4232 module_spec.GetArchitecture() =
4233 frame_module_sp->GetArchitecture();
4234 module_spec.GetFileSpec() =
4235 frame_module_sp->GetPlatformFileSpec();
4237 module_spec.GetUUID() = frame_module_sp->GetUUID();
4238 success = module_spec.GetUUID().IsValid() ||
4239 module_spec.GetFileSpec();
4240 } else {
4241 result.AppendError("frame has no module");
4242 error_set = true;
4244 } else {
4245 result.AppendError("invalid current frame");
4246 error_set = true;
4248 } else {
4249 result.AppendErrorWithFormat("process is not stopped: %s",
4250 StateAsCString(process_state));
4251 error_set = true;
4253 } else {
4254 result.AppendError(
4255 "a process must exist in order to use the --frame option");
4256 error_set = true;
4258 } else {
4259 if (uuid_option_set) {
4260 module_spec.GetUUID() =
4261 m_uuid_option_group.GetOptionValue().GetCurrentValue();
4262 success |= module_spec.GetUUID().IsValid();
4263 } else if (file_option_set) {
4264 module_spec.GetFileSpec() =
4265 m_file_option.GetOptionValue().GetCurrentValue();
4266 ModuleSP module_sp(
4267 target->GetImages().FindFirstModule(module_spec));
4268 if (module_sp) {
4269 module_spec.GetFileSpec() = module_sp->GetFileSpec();
4270 module_spec.GetPlatformFileSpec() =
4271 module_sp->GetPlatformFileSpec();
4272 module_spec.GetUUID() = module_sp->GetUUID();
4273 module_spec.GetArchitecture() = module_sp->GetArchitecture();
4274 } else {
4275 module_spec.GetArchitecture() = target->GetArchitecture();
4277 success |= module_spec.GetUUID().IsValid() ||
4278 FileSystem::Instance().Exists(module_spec.GetFileSpec());
4282 if (success) {
4283 if (Symbols::DownloadObjectAndSymbolFile(module_spec)) {
4284 if (module_spec.GetSymbolFileSpec())
4285 success = AddModuleSymbols(target, module_spec, flush, result);
4289 if (!success && !error_set) {
4290 StreamString error_strm;
4291 if (uuid_option_set) {
4292 error_strm.PutCString("unable to find debug symbols for UUID ");
4293 module_spec.GetUUID().Dump(&error_strm);
4294 } else if (file_option_set) {
4295 error_strm.PutCString(
4296 "unable to find debug symbols for the executable file ");
4297 error_strm << module_spec.GetFileSpec();
4298 } else if (frame_option_set) {
4299 error_strm.PutCString(
4300 "unable to find debug symbols for the current frame");
4302 result.AppendError(error_strm.GetString());
4304 } else {
4305 result.AppendError("one or more symbol file paths must be specified, "
4306 "or options must be specified");
4308 } else {
4309 if (uuid_option_set) {
4310 result.AppendError("specify either one or more paths to symbol files "
4311 "or use the --uuid option without arguments");
4312 } else if (frame_option_set) {
4313 result.AppendError("specify either one or more paths to symbol files "
4314 "or use the --frame option without arguments");
4315 } else if (file_option_set && argc > 1) {
4316 result.AppendError("specify at most one symbol file path when "
4317 "--shlib option is set");
4318 } else {
4319 PlatformSP platform_sp(target->GetPlatform());
4321 for (auto &entry : args.entries()) {
4322 if (!entry.ref().empty()) {
4323 auto &symbol_file_spec = module_spec.GetSymbolFileSpec();
4324 symbol_file_spec.SetFile(entry.ref(), FileSpec::Style::native);
4325 FileSystem::Instance().Resolve(symbol_file_spec);
4326 if (file_option_set) {
4327 module_spec.GetFileSpec() =
4328 m_file_option.GetOptionValue().GetCurrentValue();
4330 if (platform_sp) {
4331 FileSpec symfile_spec;
4332 if (platform_sp
4333 ->ResolveSymbolFile(*target, module_spec, symfile_spec)
4334 .Success())
4335 module_spec.GetSymbolFileSpec() = symfile_spec;
4338 ArchSpec arch;
4339 bool symfile_exists =
4340 FileSystem::Instance().Exists(module_spec.GetSymbolFileSpec());
4342 if (symfile_exists) {
4343 if (!AddModuleSymbols(target, module_spec, flush, result))
4344 break;
4345 } else {
4346 std::string resolved_symfile_path =
4347 module_spec.GetSymbolFileSpec().GetPath();
4348 if (resolved_symfile_path != entry.ref()) {
4349 result.AppendErrorWithFormat(
4350 "invalid module path '%s' with resolved path '%s'\n",
4351 entry.c_str(), resolved_symfile_path.c_str());
4352 break;
4354 result.AppendErrorWithFormat("invalid module path '%s'\n",
4355 entry.c_str());
4356 break;
4363 if (flush) {
4364 Process *process = m_exe_ctx.GetProcessPtr();
4365 if (process)
4366 process->Flush();
4368 return result.Succeeded();
4371 OptionGroupOptions m_option_group;
4372 OptionGroupUUID m_uuid_option_group;
4373 OptionGroupFile m_file_option;
4374 OptionGroupBoolean m_current_frame_option;
4377 #pragma mark CommandObjectTargetSymbols
4379 // CommandObjectTargetSymbols
4381 class CommandObjectTargetSymbols : public CommandObjectMultiword {
4382 public:
4383 // Constructors and Destructors
4384 CommandObjectTargetSymbols(CommandInterpreter &interpreter)
4385 : CommandObjectMultiword(
4386 interpreter, "target symbols",
4387 "Commands for adding and managing debug symbol files.",
4388 "target symbols <sub-command> ...") {
4389 LoadSubCommand(
4390 "add", CommandObjectSP(new CommandObjectTargetSymbolsAdd(interpreter)));
4393 ~CommandObjectTargetSymbols() override = default;
4395 private:
4396 // For CommandObjectTargetModules only
4397 DISALLOW_COPY_AND_ASSIGN(CommandObjectTargetSymbols);
4400 #pragma mark CommandObjectTargetStopHookAdd
4402 // CommandObjectTargetStopHookAdd
4403 #define LLDB_OPTIONS_target_stop_hook_add
4404 #include "CommandOptions.inc"
4406 class CommandObjectTargetStopHookAdd : public CommandObjectParsed,
4407 public IOHandlerDelegateMultiline {
4408 public:
4409 class CommandOptions : public Options {
4410 public:
4411 CommandOptions()
4412 : Options(), m_line_start(0), m_line_end(UINT_MAX),
4413 m_func_name_type_mask(eFunctionNameTypeAuto),
4414 m_sym_ctx_specified(false), m_thread_specified(false),
4415 m_use_one_liner(false), m_one_liner() {}
4417 ~CommandOptions() override = default;
4419 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
4420 return llvm::makeArrayRef(g_target_stop_hook_add_options);
4423 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
4424 ExecutionContext *execution_context) override {
4425 Status error;
4426 const int short_option = m_getopt_table[option_idx].val;
4428 switch (short_option) {
4429 case 'c':
4430 m_class_name = option_arg;
4431 m_sym_ctx_specified = true;
4432 break;
4434 case 'e':
4435 if (option_arg.getAsInteger(0, m_line_end)) {
4436 error.SetErrorStringWithFormat("invalid end line number: \"%s\"",
4437 option_arg.str().c_str());
4438 break;
4440 m_sym_ctx_specified = true;
4441 break;
4443 case 'G': {
4444 bool value, success;
4445 value = OptionArgParser::ToBoolean(option_arg, false, &success);
4446 if (success) {
4447 m_auto_continue = value;
4448 } else
4449 error.SetErrorStringWithFormat(
4450 "invalid boolean value '%s' passed for -G option",
4451 option_arg.str().c_str());
4452 } break;
4453 case 'l':
4454 if (option_arg.getAsInteger(0, m_line_start)) {
4455 error.SetErrorStringWithFormat("invalid start line number: \"%s\"",
4456 option_arg.str().c_str());
4457 break;
4459 m_sym_ctx_specified = true;
4460 break;
4462 case 'i':
4463 m_no_inlines = true;
4464 break;
4466 case 'n':
4467 m_function_name = option_arg;
4468 m_func_name_type_mask |= eFunctionNameTypeAuto;
4469 m_sym_ctx_specified = true;
4470 break;
4472 case 'f':
4473 m_file_name = option_arg;
4474 m_sym_ctx_specified = true;
4475 break;
4477 case 's':
4478 m_module_name = option_arg;
4479 m_sym_ctx_specified = true;
4480 break;
4482 case 't':
4483 if (option_arg.getAsInteger(0, m_thread_id))
4484 error.SetErrorStringWithFormat("invalid thread id string '%s'",
4485 option_arg.str().c_str());
4486 m_thread_specified = true;
4487 break;
4489 case 'T':
4490 m_thread_name = option_arg;
4491 m_thread_specified = true;
4492 break;
4494 case 'q':
4495 m_queue_name = option_arg;
4496 m_thread_specified = true;
4497 break;
4499 case 'x':
4500 if (option_arg.getAsInteger(0, m_thread_index))
4501 error.SetErrorStringWithFormat("invalid thread index string '%s'",
4502 option_arg.str().c_str());
4503 m_thread_specified = true;
4504 break;
4506 case 'o':
4507 m_use_one_liner = true;
4508 m_one_liner.push_back(option_arg);
4509 break;
4511 default:
4512 llvm_unreachable("Unimplemented option");
4514 return error;
4517 void OptionParsingStarting(ExecutionContext *execution_context) override {
4518 m_class_name.clear();
4519 m_function_name.clear();
4520 m_line_start = 0;
4521 m_line_end = UINT_MAX;
4522 m_file_name.clear();
4523 m_module_name.clear();
4524 m_func_name_type_mask = eFunctionNameTypeAuto;
4525 m_thread_id = LLDB_INVALID_THREAD_ID;
4526 m_thread_index = UINT32_MAX;
4527 m_thread_name.clear();
4528 m_queue_name.clear();
4530 m_no_inlines = false;
4531 m_sym_ctx_specified = false;
4532 m_thread_specified = false;
4534 m_use_one_liner = false;
4535 m_one_liner.clear();
4536 m_auto_continue = false;
4539 std::string m_class_name;
4540 std::string m_function_name;
4541 uint32_t m_line_start;
4542 uint32_t m_line_end;
4543 std::string m_file_name;
4544 std::string m_module_name;
4545 uint32_t m_func_name_type_mask; // A pick from lldb::FunctionNameType.
4546 lldb::tid_t m_thread_id;
4547 uint32_t m_thread_index;
4548 std::string m_thread_name;
4549 std::string m_queue_name;
4550 bool m_sym_ctx_specified;
4551 bool m_no_inlines;
4552 bool m_thread_specified;
4553 // Instance variables to hold the values for one_liner options.
4554 bool m_use_one_liner;
4555 std::vector<std::string> m_one_liner;
4556 bool m_auto_continue;
4559 CommandObjectTargetStopHookAdd(CommandInterpreter &interpreter)
4560 : CommandObjectParsed(interpreter, "target stop-hook add",
4561 "Add a hook to be executed when the target stops.",
4562 "target stop-hook add"),
4563 IOHandlerDelegateMultiline("DONE",
4564 IOHandlerDelegate::Completion::LLDBCommand),
4565 m_options() {}
4567 ~CommandObjectTargetStopHookAdd() override = default;
4569 Options *GetOptions() override { return &m_options; }
4571 protected:
4572 void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
4573 StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
4574 if (output_sp && interactive) {
4575 output_sp->PutCString(
4576 "Enter your stop hook command(s). Type 'DONE' to end.\n");
4577 output_sp->Flush();
4581 void IOHandlerInputComplete(IOHandler &io_handler,
4582 std::string &line) override {
4583 if (m_stop_hook_sp) {
4584 if (line.empty()) {
4585 StreamFileSP error_sp(io_handler.GetErrorStreamFileSP());
4586 if (error_sp) {
4587 error_sp->Printf("error: stop hook #%" PRIu64
4588 " aborted, no commands.\n",
4589 m_stop_hook_sp->GetID());
4590 error_sp->Flush();
4592 Target *target = GetDebugger().GetSelectedTarget().get();
4593 if (target)
4594 target->RemoveStopHookByID(m_stop_hook_sp->GetID());
4595 } else {
4596 m_stop_hook_sp->GetCommandPointer()->SplitIntoLines(line);
4597 StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
4598 if (output_sp) {
4599 output_sp->Printf("Stop hook #%" PRIu64 " added.\n",
4600 m_stop_hook_sp->GetID());
4601 output_sp->Flush();
4604 m_stop_hook_sp.reset();
4606 io_handler.SetIsDone(true);
4609 bool DoExecute(Args &command, CommandReturnObject &result) override {
4610 m_stop_hook_sp.reset();
4612 Target &target = GetSelectedOrDummyTarget();
4613 Target::StopHookSP new_hook_sp = target.CreateStopHook();
4615 // First step, make the specifier.
4616 std::unique_ptr<SymbolContextSpecifier> specifier_up;
4617 if (m_options.m_sym_ctx_specified) {
4618 specifier_up.reset(
4619 new SymbolContextSpecifier(GetDebugger().GetSelectedTarget()));
4621 if (!m_options.m_module_name.empty()) {
4622 specifier_up->AddSpecification(
4623 m_options.m_module_name.c_str(),
4624 SymbolContextSpecifier::eModuleSpecified);
4627 if (!m_options.m_class_name.empty()) {
4628 specifier_up->AddSpecification(
4629 m_options.m_class_name.c_str(),
4630 SymbolContextSpecifier::eClassOrNamespaceSpecified);
4633 if (!m_options.m_file_name.empty()) {
4634 specifier_up->AddSpecification(m_options.m_file_name.c_str(),
4635 SymbolContextSpecifier::eFileSpecified);
4638 if (m_options.m_line_start != 0) {
4639 specifier_up->AddLineSpecification(
4640 m_options.m_line_start,
4641 SymbolContextSpecifier::eLineStartSpecified);
4644 if (m_options.m_line_end != UINT_MAX) {
4645 specifier_up->AddLineSpecification(
4646 m_options.m_line_end, SymbolContextSpecifier::eLineEndSpecified);
4649 if (!m_options.m_function_name.empty()) {
4650 specifier_up->AddSpecification(
4651 m_options.m_function_name.c_str(),
4652 SymbolContextSpecifier::eFunctionSpecified);
4656 if (specifier_up)
4657 new_hook_sp->SetSpecifier(specifier_up.release());
4659 // Next see if any of the thread options have been entered:
4661 if (m_options.m_thread_specified) {
4662 ThreadSpec *thread_spec = new ThreadSpec();
4664 if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID) {
4665 thread_spec->SetTID(m_options.m_thread_id);
4668 if (m_options.m_thread_index != UINT32_MAX)
4669 thread_spec->SetIndex(m_options.m_thread_index);
4671 if (!m_options.m_thread_name.empty())
4672 thread_spec->SetName(m_options.m_thread_name.c_str());
4674 if (!m_options.m_queue_name.empty())
4675 thread_spec->SetQueueName(m_options.m_queue_name.c_str());
4677 new_hook_sp->SetThreadSpecifier(thread_spec);
4680 new_hook_sp->SetAutoContinue(m_options.m_auto_continue);
4681 if (m_options.m_use_one_liner) {
4682 // Use one-liners.
4683 for (auto cmd : m_options.m_one_liner)
4684 new_hook_sp->GetCommandPointer()->AppendString(cmd.c_str());
4685 result.AppendMessageWithFormat("Stop hook #%" PRIu64 " added.\n",
4686 new_hook_sp->GetID());
4687 } else {
4688 m_stop_hook_sp = new_hook_sp;
4689 m_interpreter.GetLLDBCommandsFromIOHandler("> ", // Prompt
4690 *this); // IOHandlerDelegate
4692 result.SetStatus(eReturnStatusSuccessFinishNoResult);
4694 return result.Succeeded();
4697 private:
4698 CommandOptions m_options;
4699 Target::StopHookSP m_stop_hook_sp;
4702 #pragma mark CommandObjectTargetStopHookDelete
4704 // CommandObjectTargetStopHookDelete
4706 class CommandObjectTargetStopHookDelete : public CommandObjectParsed {
4707 public:
4708 CommandObjectTargetStopHookDelete(CommandInterpreter &interpreter)
4709 : CommandObjectParsed(interpreter, "target stop-hook delete",
4710 "Delete a stop-hook.",
4711 "target stop-hook delete [<idx>]") {}
4713 ~CommandObjectTargetStopHookDelete() override = default;
4715 protected:
4716 bool DoExecute(Args &command, CommandReturnObject &result) override {
4717 Target &target = GetSelectedOrDummyTarget();
4718 // FIXME: see if we can use the breakpoint id style parser?
4719 size_t num_args = command.GetArgumentCount();
4720 if (num_args == 0) {
4721 if (!m_interpreter.Confirm("Delete all stop hooks?", true)) {
4722 result.SetStatus(eReturnStatusFailed);
4723 return false;
4724 } else {
4725 target.RemoveAllStopHooks();
4727 } else {
4728 bool success;
4729 for (size_t i = 0; i < num_args; i++) {
4730 lldb::user_id_t user_id = StringConvert::ToUInt32(
4731 command.GetArgumentAtIndex(i), 0, 0, &success);
4732 if (!success) {
4733 result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n",
4734 command.GetArgumentAtIndex(i));
4735 result.SetStatus(eReturnStatusFailed);
4736 return false;
4738 success = target.RemoveStopHookByID(user_id);
4739 if (!success) {
4740 result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n",
4741 command.GetArgumentAtIndex(i));
4742 result.SetStatus(eReturnStatusFailed);
4743 return false;
4747 result.SetStatus(eReturnStatusSuccessFinishNoResult);
4748 return result.Succeeded();
4752 #pragma mark CommandObjectTargetStopHookEnableDisable
4754 // CommandObjectTargetStopHookEnableDisable
4756 class CommandObjectTargetStopHookEnableDisable : public CommandObjectParsed {
4757 public:
4758 CommandObjectTargetStopHookEnableDisable(CommandInterpreter &interpreter,
4759 bool enable, const char *name,
4760 const char *help, const char *syntax)
4761 : CommandObjectParsed(interpreter, name, help, syntax), m_enable(enable) {
4764 ~CommandObjectTargetStopHookEnableDisable() override = default;
4766 protected:
4767 bool DoExecute(Args &command, CommandReturnObject &result) override {
4768 Target &target = GetSelectedOrDummyTarget();
4769 // FIXME: see if we can use the breakpoint id style parser?
4770 size_t num_args = command.GetArgumentCount();
4771 bool success;
4773 if (num_args == 0) {
4774 target.SetAllStopHooksActiveState(m_enable);
4775 } else {
4776 for (size_t i = 0; i < num_args; i++) {
4777 lldb::user_id_t user_id = StringConvert::ToUInt32(
4778 command.GetArgumentAtIndex(i), 0, 0, &success);
4779 if (!success) {
4780 result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n",
4781 command.GetArgumentAtIndex(i));
4782 result.SetStatus(eReturnStatusFailed);
4783 return false;
4785 success = target.SetStopHookActiveStateByID(user_id, m_enable);
4786 if (!success) {
4787 result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n",
4788 command.GetArgumentAtIndex(i));
4789 result.SetStatus(eReturnStatusFailed);
4790 return false;
4794 result.SetStatus(eReturnStatusSuccessFinishNoResult);
4795 return result.Succeeded();
4798 private:
4799 bool m_enable;
4802 #pragma mark CommandObjectTargetStopHookList
4804 // CommandObjectTargetStopHookList
4806 class CommandObjectTargetStopHookList : public CommandObjectParsed {
4807 public:
4808 CommandObjectTargetStopHookList(CommandInterpreter &interpreter)
4809 : CommandObjectParsed(interpreter, "target stop-hook list",
4810 "List all stop-hooks.",
4811 "target stop-hook list [<type>]") {}
4813 ~CommandObjectTargetStopHookList() override = default;
4815 protected:
4816 bool DoExecute(Args &command, CommandReturnObject &result) override {
4817 Target &target = GetSelectedOrDummyTarget();
4819 size_t num_hooks = target.GetNumStopHooks();
4820 if (num_hooks == 0) {
4821 result.GetOutputStream().PutCString("No stop hooks.\n");
4822 } else {
4823 for (size_t i = 0; i < num_hooks; i++) {
4824 Target::StopHookSP this_hook = target.GetStopHookAtIndex(i);
4825 if (i > 0)
4826 result.GetOutputStream().PutCString("\n");
4827 this_hook->GetDescription(&(result.GetOutputStream()),
4828 eDescriptionLevelFull);
4831 result.SetStatus(eReturnStatusSuccessFinishResult);
4832 return result.Succeeded();
4836 #pragma mark CommandObjectMultiwordTargetStopHooks
4838 // CommandObjectMultiwordTargetStopHooks
4840 class CommandObjectMultiwordTargetStopHooks : public CommandObjectMultiword {
4841 public:
4842 CommandObjectMultiwordTargetStopHooks(CommandInterpreter &interpreter)
4843 : CommandObjectMultiword(
4844 interpreter, "target stop-hook",
4845 "Commands for operating on debugger target stop-hooks.",
4846 "target stop-hook <subcommand> [<subcommand-options>]") {
4847 LoadSubCommand("add", CommandObjectSP(
4848 new CommandObjectTargetStopHookAdd(interpreter)));
4849 LoadSubCommand(
4850 "delete",
4851 CommandObjectSP(new CommandObjectTargetStopHookDelete(interpreter)));
4852 LoadSubCommand("disable",
4853 CommandObjectSP(new CommandObjectTargetStopHookEnableDisable(
4854 interpreter, false, "target stop-hook disable [<id>]",
4855 "Disable a stop-hook.", "target stop-hook disable")));
4856 LoadSubCommand("enable",
4857 CommandObjectSP(new CommandObjectTargetStopHookEnableDisable(
4858 interpreter, true, "target stop-hook enable [<id>]",
4859 "Enable a stop-hook.", "target stop-hook enable")));
4860 LoadSubCommand("list", CommandObjectSP(new CommandObjectTargetStopHookList(
4861 interpreter)));
4864 ~CommandObjectMultiwordTargetStopHooks() override = default;
4867 #pragma mark CommandObjectMultiwordTarget
4869 // CommandObjectMultiwordTarget
4871 CommandObjectMultiwordTarget::CommandObjectMultiwordTarget(
4872 CommandInterpreter &interpreter)
4873 : CommandObjectMultiword(interpreter, "target",
4874 "Commands for operating on debugger targets.",
4875 "target <subcommand> [<subcommand-options>]") {
4876 LoadSubCommand("create",
4877 CommandObjectSP(new CommandObjectTargetCreate(interpreter)));
4878 LoadSubCommand("delete",
4879 CommandObjectSP(new CommandObjectTargetDelete(interpreter)));
4880 LoadSubCommand("list",
4881 CommandObjectSP(new CommandObjectTargetList(interpreter)));
4882 LoadSubCommand("select",
4883 CommandObjectSP(new CommandObjectTargetSelect(interpreter)));
4884 LoadSubCommand(
4885 "stop-hook",
4886 CommandObjectSP(new CommandObjectMultiwordTargetStopHooks(interpreter)));
4887 LoadSubCommand("modules",
4888 CommandObjectSP(new CommandObjectTargetModules(interpreter)));
4889 LoadSubCommand("symbols",
4890 CommandObjectSP(new CommandObjectTargetSymbols(interpreter)));
4891 LoadSubCommand("variable",
4892 CommandObjectSP(new CommandObjectTargetVariable(interpreter)));
4895 CommandObjectMultiwordTarget::~CommandObjectMultiwordTarget() = default;