56#include "lldb/Host/Config.h"
57#if LLDB_ENABLE_LIBEDIT
80#include "llvm/ADT/STLExtras.h"
81#include "llvm/ADT/ScopeExit.h"
82#include "llvm/ADT/SmallString.h"
83#include "llvm/Support/FormatAdapters.h"
84#include "llvm/Support/Path.h"
85#include "llvm/Support/PrettyStackTrace.h"
86#include "llvm/Support/ScopedPrinter.h"
89#include <TargetConditionals.h>
98 "There is a .lldbinit file in the current directory which is not being "
100 "To silence this warning without sourcing in the local .lldbinit,\n"
101 "add the following to the lldbinit file in your home directory:\n"
102 " settings set target.load-cwd-lldbinit false\n"
103 "To allow lldb to source .lldbinit files in the current working "
105 "set the value of this variable to true. Only do so if you understand "
107 "accept the security risk.";
114#define LLDB_PROPERTIES_interpreter
115#include "InterpreterProperties.inc"
118#define LLDB_PROPERTIES_interpreter
119#include "InterpreterPropertiesEnum.inc"
123 static ConstString class_name(
"lldb.commandInterpreter");
128 bool synchronous_execution)
134 m_debugger(debugger), m_synchronous_execution(true),
135 m_skip_lldbinit_files(false), m_skip_app_init_files(false),
136 m_comment_char(
'#'), m_batch_command_mode(false),
137 m_truncation_warning(eNoOmission), m_max_depth_warning(eNoOmission),
138 m_command_source_depth(0) {
148 const uint32_t idx = ePropertyExpandRegexAliases;
150 nullptr, idx, g_interpreter_properties[idx].default_uint_value != 0);
154 const uint32_t idx = ePropertyPromptOnQuit;
156 nullptr, idx, g_interpreter_properties[idx].default_uint_value != 0);
160 const uint32_t idx = ePropertyPromptOnQuit;
165 const uint32_t idx = ePropertySaveSessionOnQuit;
167 nullptr, idx, g_interpreter_properties[idx].default_uint_value != 0);
171 const uint32_t idx = ePropertySaveSessionOnQuit;
176 const uint32_t idx = ePropertyOpenTranscriptInEditor;
178 nullptr, idx, g_interpreter_properties[idx].default_uint_value != 0);
182 const uint32_t idx = ePropertyOpenTranscriptInEditor;
187 const uint32_t idx = ePropertySaveSessionDirectory;
192 const uint32_t idx = ePropertySaveSessionDirectory;
197 const uint32_t idx = ePropertyEchoCommands;
199 nullptr, idx, g_interpreter_properties[idx].default_uint_value != 0);
203 const uint32_t idx = ePropertyEchoCommands;
208 const uint32_t idx = ePropertyEchoCommentCommands;
210 nullptr, idx, g_interpreter_properties[idx].default_uint_value != 0);
214 const uint32_t idx = ePropertyEchoCommentCommands;
240 std::string command = command_line;
248 const uint32_t idx = ePropertyStopCmdSourceOnError;
250 nullptr, idx, g_interpreter_properties[idx].default_uint_value != 0);
254 const uint32_t idx = ePropertySpaceReplPrompts;
256 nullptr, idx, g_interpreter_properties[idx].default_uint_value != 0);
260 const uint32_t idx = ePropertyRepeatPreviousCommand;
262 nullptr, idx, g_interpreter_properties[idx].default_uint_value != 0);
266 const uint32_t idx = ePropertyRequireCommandOverwrite;
268 nullptr, idx, g_interpreter_properties[idx].default_uint_value != 0);
328 "sif", cmd_obj_sp,
"--end-linenumber block --step-in-target %1");
330 sif_alias->
SetHelp(
"Step through the current block, stopping if you step "
331 "directly into a function whose name matches the "
332 "TargetFunctionName.");
333 sif_alias->
SetSyntax(
"sif <TargetFunctionName>");
414 alias_arguments_vector_sp = std::make_shared<OptionArgVector>();
421 if (
auto *po =
AddAlias(
"po", cmd_obj_sp,
"-O --")) {
422 po->SetHelp(
"Evaluate an expression on the current thread. Displays any "
423 "returned value with formatting "
424 "controlled by the type's author.");
428 AddAlias(
"parray", cmd_obj_sp,
"--element-count %1 --");
431 (
"parray <COUNT> <EXPRESSION> -- lldb will evaluate EXPRESSION "
432 "to get a typed-pointer-to-an-array in memory, and will display "
433 "COUNT elements of that type from the array.");
437 "--object-description --element-count %1 --");
439 poarray_alias->
SetHelp(
"poarray <COUNT> <EXPRESSION> -- lldb will "
440 "evaluate EXPRESSION to get the address of an array of COUNT "
441 "objects in memory, and will call po on them.");
450 shell_alias->
SetHelp(
"Run a shell command on the host.");
452 shell_alias->
SetSyntax(
"shell <shell-command>");
463 alias_arguments_vector_sp = std::make_shared<OptionArgVector>();
464#if defined(__APPLE__)
469 AddAlias(
"r", cmd_obj_sp,
"--shell-expand-args true --");
470 AddAlias(
"run", cmd_obj_sp,
"--shell-expand-args true --");
474 defaultshell.
Printf(
"--shell=%s --",
475 HostInfo::GetDefaultShell().GetPath().c_str());
488 AddAlias(
"rbreak", cmd_obj_sp,
"--func-regex %1");
495 AddAlias(
"vo", cmd_obj_sp,
"--object-description");
526#define REGISTER_COMMAND_OBJECT(NAME, CLASS) \
527 m_command_dict[NAME] = std::make_shared<CLASS>(*this);
563 const char *break_regexes[][2] = {
564 {
"^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$",
565 "breakpoint set --file '%1' --line %2 --column %3"},
566 {
"^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$",
567 "breakpoint set --file '%1' --line %2"},
568 {
"^/([^/]+)/$",
"breakpoint set --source-pattern-regexp '%1'"},
569 {
"^([[:digit:]]+)[[:space:]]*$",
"breakpoint set --line %1"},
570 {
"^\\*?(0x[[:xdigit:]]+)[[:space:]]*$",
"breakpoint set --address %1"},
571 {
"^[\"']?([-+]?\\[.*\\])[\"']?[[:space:]]*$",
572 "breakpoint set --name '%1'"},
573 {
"^(-.*)$",
"breakpoint set %1"},
574 {
"^(.*[^[:space:]])`(.*[^[:space:]])[[:space:]]*$",
575 "breakpoint set --name '%2' --shlib '%1'"},
576 {
"^\\&(.*[^[:space:]])[[:space:]]*$",
577 "breakpoint set --name '%1' --skip-prologue=0"},
578 {
"^[\"']?(.*[^[:space:]\"'])[\"']?[[:space:]]*$",
579 "breakpoint set --name '%1'"}};
582 size_t num_regexes = std::size(break_regexes);
584 std::unique_ptr<CommandObjectRegexCommand> break_regex_cmd_up(
586 *
this,
"_regexp-break",
587 "Set a breakpoint using one of several shorthand formats.",
589 "_regexp-break <filename>:<linenum>:<colnum>\n"
590 " main.c:12:21 // Break at line 12 and column "
592 "_regexp-break <filename>:<linenum>\n"
593 " main.c:12 // Break at line 12 of "
595 "_regexp-break <linenum>\n"
596 " 12 // Break at line 12 of current "
598 "_regexp-break 0x<address>\n"
599 " 0x1234000 // Break at address "
601 "_regexp-break <name>\n"
602 " main // Break in 'main' after the "
604 "_regexp-break &<name>\n"
605 " &main // Break at first instruction "
607 "_regexp-break <module>`<name>\n"
608 " libc.so`malloc // Break in 'malloc' from "
610 "_regexp-break /<source-regex>/\n"
611 " /break here/ // Break on source lines in "
613 " // containing text 'break "
620 if (break_regex_cmd_up) {
622 for (
size_t i = 0; i < num_regexes; i++) {
623 success = break_regex_cmd_up->AddRegexCommand(break_regexes[i][0],
624 break_regexes[i][1]);
629 break_regex_cmd_up->AddRegexCommand(
"^$",
"breakpoint list --full");
632 CommandObjectSP break_regex_cmd_sp(break_regex_cmd_up.release());
633 m_command_dict[std::string(break_regex_cmd_sp->GetCommandName())] =
638 std::unique_ptr<CommandObjectRegexCommand> tbreak_regex_cmd_up(
640 *
this,
"_regexp-tbreak",
641 "Set a one-shot breakpoint using one of several shorthand formats.",
643 "_regexp-break <filename>:<linenum>:<colnum>\n"
644 " main.c:12:21 // Break at line 12 and column "
646 "_regexp-break <filename>:<linenum>\n"
647 " main.c:12 // Break at line 12 of "
649 "_regexp-break <linenum>\n"
650 " 12 // Break at line 12 of current "
652 "_regexp-break 0x<address>\n"
653 " 0x1234000 // Break at address "
655 "_regexp-break <name>\n"
656 " main // Break in 'main' after the "
658 "_regexp-break &<name>\n"
659 " &main // Break at first instruction "
661 "_regexp-break <module>`<name>\n"
662 " libc.so`malloc // Break in 'malloc' from "
664 "_regexp-break /<source-regex>/\n"
665 " /break here/ // Break on source lines in "
667 " // containing text 'break "
674 if (tbreak_regex_cmd_up) {
676 for (
size_t i = 0; i < num_regexes; i++) {
677 std::string command = break_regexes[i][1];
680 tbreak_regex_cmd_up->AddRegexCommand(break_regexes[i][0], command);
685 tbreak_regex_cmd_up->AddRegexCommand(
"^$",
"breakpoint list --full");
688 CommandObjectSP tbreak_regex_cmd_sp(tbreak_regex_cmd_up.release());
689 m_command_dict[std::string(tbreak_regex_cmd_sp->GetCommandName())] =
694 std::unique_ptr<CommandObjectRegexCommand> attach_regex_cmd_up(
696 *
this,
"_regexp-attach",
"Attach to process by ID or name.",
697 "_regexp-attach <pid> | <process-name>", 2, 0,
false));
698 if (attach_regex_cmd_up) {
699 if (attach_regex_cmd_up->AddRegexCommand(
"^([0-9]+)[[:space:]]*$",
700 "process attach --pid %1") &&
701 attach_regex_cmd_up->AddRegexCommand(
702 "^(-.*|.* -.*)$",
"process attach %1") &&
705 attach_regex_cmd_up->AddRegexCommand(
"^(.+)$",
706 "process attach --name '%1'") &&
707 attach_regex_cmd_up->AddRegexCommand(
"^$",
"process attach")) {
708 CommandObjectSP attach_regex_cmd_sp(attach_regex_cmd_up.release());
709 m_command_dict[std::string(attach_regex_cmd_sp->GetCommandName())] =
714 std::unique_ptr<CommandObjectRegexCommand> down_regex_cmd_up(
716 "Select a newer stack frame. Defaults to "
717 "moving one frame, a numeric argument can "
718 "specify an arbitrary number.",
719 "_regexp-down [<count>]", 2, 0,
false));
720 if (down_regex_cmd_up) {
721 if (down_regex_cmd_up->AddRegexCommand(
"^$",
"frame select -r -1") &&
722 down_regex_cmd_up->AddRegexCommand(
"^([0-9]+)$",
723 "frame select -r -%1")) {
724 CommandObjectSP down_regex_cmd_sp(down_regex_cmd_up.release());
725 m_command_dict[std::string(down_regex_cmd_sp->GetCommandName())] =
730 std::unique_ptr<CommandObjectRegexCommand> up_regex_cmd_up(
733 "Select an older stack frame. Defaults to moving one "
734 "frame, a numeric argument can specify an arbitrary number.",
735 "_regexp-up [<count>]", 2, 0,
false));
736 if (up_regex_cmd_up) {
737 if (up_regex_cmd_up->AddRegexCommand(
"^$",
"frame select -r 1") &&
738 up_regex_cmd_up->AddRegexCommand(
"^([0-9]+)$",
"frame select -r %1")) {
739 CommandObjectSP up_regex_cmd_sp(up_regex_cmd_up.release());
745 std::unique_ptr<CommandObjectRegexCommand> display_regex_cmd_up(
747 *
this,
"_regexp-display",
748 "Evaluate an expression at every stop (see 'help target stop-hook'.)",
749 "_regexp-display expression", 2, 0,
false));
750 if (display_regex_cmd_up) {
751 if (display_regex_cmd_up->AddRegexCommand(
752 "^(.+)$",
"target stop-hook add -o \"expr -- %1\"")) {
753 CommandObjectSP display_regex_cmd_sp(display_regex_cmd_up.release());
754 m_command_dict[std::string(display_regex_cmd_sp->GetCommandName())] =
755 display_regex_cmd_sp;
759 std::unique_ptr<CommandObjectRegexCommand> undisplay_regex_cmd_up(
761 "Stop displaying expression at every "
762 "stop (specified by stop-hook index.)",
763 "_regexp-undisplay stop-hook-number", 2, 0,
765 if (undisplay_regex_cmd_up) {
766 if (undisplay_regex_cmd_up->AddRegexCommand(
"^([0-9]+)$",
767 "target stop-hook delete %1")) {
768 CommandObjectSP undisplay_regex_cmd_sp(undisplay_regex_cmd_up.release());
769 m_command_dict[std::string(undisplay_regex_cmd_sp->GetCommandName())] =
770 undisplay_regex_cmd_sp;
774 std::unique_ptr<CommandObjectRegexCommand> connect_gdb_remote_cmd_up(
777 "Connect to a process via remote GDB server.\n"
778 "If no host is specifed, localhost is assumed.\n"
779 "gdb-remote is an abbreviation for 'process connect --plugin "
780 "gdb-remote connect://<hostname>:<port>'\n",
781 "gdb-remote [<hostname>:]<portnum>", 2, 0,
false));
782 if (connect_gdb_remote_cmd_up) {
783 if (connect_gdb_remote_cmd_up->AddRegexCommand(
784 "^([^:]+|\\[[0-9a-fA-F:]+.*\\]):([0-9]+)$",
785 "process connect --plugin gdb-remote connect://%1:%2") &&
786 connect_gdb_remote_cmd_up->AddRegexCommand(
788 "process connect --plugin gdb-remote connect://localhost:%1")) {
789 CommandObjectSP command_sp(connect_gdb_remote_cmd_up.release());
790 m_command_dict[std::string(command_sp->GetCommandName())] = command_sp;
794 std::unique_ptr<CommandObjectRegexCommand> connect_kdp_remote_cmd_up(
797 "Connect to a process via remote KDP server.\n"
798 "If no UDP port is specified, port 41139 is assumed.\n"
799 "kdp-remote is an abbreviation for 'process connect --plugin "
800 "kdp-remote udp://<hostname>:<port>'\n",
801 "kdp-remote <hostname>[:<portnum>]", 2, 0,
false));
802 if (connect_kdp_remote_cmd_up) {
803 if (connect_kdp_remote_cmd_up->AddRegexCommand(
804 "^([^:]+:[[:digit:]]+)$",
805 "process connect --plugin kdp-remote udp://%1") &&
806 connect_kdp_remote_cmd_up->AddRegexCommand(
807 "^(.+)$",
"process connect --plugin kdp-remote udp://%1:41139")) {
808 CommandObjectSP command_sp(connect_kdp_remote_cmd_up.release());
809 m_command_dict[std::string(command_sp->GetCommandName())] = command_sp;
813 std::unique_ptr<CommandObjectRegexCommand> bt_regex_cmd_up(
816 "Show the current thread's call stack. Any numeric argument "
817 "displays at most that many "
818 "frames. The argument 'all' displays all threads. Use 'settings"
819 " set frame-format' to customize the printing of individual frames "
820 "and 'settings set thread-format' to customize the thread header.",
821 "bt [<digit> | all]", 2, 0,
false));
822 if (bt_regex_cmd_up) {
827 if (bt_regex_cmd_up->AddRegexCommand(
"^([[:digit:]]+)[[:space:]]*$",
828 "thread backtrace -c %1") &&
829 bt_regex_cmd_up->AddRegexCommand(
"^-c ([[:digit:]]+)[[:space:]]*$",
830 "thread backtrace -c %1") &&
831 bt_regex_cmd_up->AddRegexCommand(
"^all[[:space:]]*$",
"thread backtrace all") &&
832 bt_regex_cmd_up->AddRegexCommand(
"^[[:space:]]*$",
"thread backtrace")) {
833 CommandObjectSP command_sp(bt_regex_cmd_up.release());
834 m_command_dict[std::string(command_sp->GetCommandName())] = command_sp;
838 std::unique_ptr<CommandObjectRegexCommand> list_regex_cmd_up(
840 *
this,
"_regexp-list",
841 "List relevant source code using one of several shorthand formats.",
843 "_regexp-list <file>:<line> // List around specific file/line\n"
844 "_regexp-list <line> // List current file around specified "
846 "_regexp-list <function-name> // List specified function\n"
847 "_regexp-list 0x<address> // List around specified address\n"
848 "_regexp-list -[<count>] // List previous <count> lines\n"
849 "_regexp-list // List subsequent lines",
851 if (list_regex_cmd_up) {
852 if (list_regex_cmd_up->AddRegexCommand(
"^([0-9]+)[[:space:]]*$",
853 "source list --line %1") &&
854 list_regex_cmd_up->AddRegexCommand(
855 "^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]"
857 "source list --file '%1' --line %2") &&
858 list_regex_cmd_up->AddRegexCommand(
859 "^\\*?(0x[[:xdigit:]]+)[[:space:]]*$",
860 "source list --address %1") &&
861 list_regex_cmd_up->AddRegexCommand(
"^-[[:space:]]*$",
862 "source list --reverse") &&
863 list_regex_cmd_up->AddRegexCommand(
864 "^-([[:digit:]]+)[[:space:]]*$",
865 "source list --reverse --count %1") &&
866 list_regex_cmd_up->AddRegexCommand(
"^(.+)$",
867 "source list --name \"%1\"") &&
868 list_regex_cmd_up->AddRegexCommand(
"^$",
"source list")) {
869 CommandObjectSP list_regex_cmd_sp(list_regex_cmd_up.release());
870 m_command_dict[std::string(list_regex_cmd_sp->GetCommandName())] =
875 std::unique_ptr<CommandObjectRegexCommand> env_regex_cmd_up(
877 *
this,
"_regexp-env",
878 "Shorthand for viewing and setting environment variables.",
880 "_regexp-env // Show environment\n"
881 "_regexp-env <name>=<value> // Set an environment variable",
883 if (env_regex_cmd_up) {
884 if (env_regex_cmd_up->AddRegexCommand(
"^$",
885 "settings show target.env-vars") &&
886 env_regex_cmd_up->AddRegexCommand(
"^([A-Za-z_][A-Za-z_0-9]*=.*)$",
887 "settings set target.env-vars %1")) {
888 CommandObjectSP env_regex_cmd_sp(env_regex_cmd_up.release());
894 std::unique_ptr<CommandObjectRegexCommand> jump_regex_cmd_up(
896 *
this,
"_regexp-jump",
"Set the program counter to a new address.",
898 "_regexp-jump <line>\n"
899 "_regexp-jump +<line-offset> | -<line-offset>\n"
900 "_regexp-jump <file>:<line>\n"
901 "_regexp-jump *<addr>\n",
903 if (jump_regex_cmd_up) {
904 if (jump_regex_cmd_up->AddRegexCommand(
"^\\*(.*)$",
905 "thread jump --addr %1") &&
906 jump_regex_cmd_up->AddRegexCommand(
"^([0-9]+)$",
907 "thread jump --line %1") &&
908 jump_regex_cmd_up->AddRegexCommand(
"^([^:]+):([0-9]+)$",
909 "thread jump --file %1 --line %2") &&
910 jump_regex_cmd_up->AddRegexCommand(
"^([+\\-][0-9]+)$",
911 "thread jump --by %1")) {
912 CommandObjectSP jump_regex_cmd_sp(jump_regex_cmd_up.release());
913 m_command_dict[std::string(jump_regex_cmd_sp->GetCommandName())] =
920 const char *cmd_str,
bool include_aliases,
StringList &matches,
925 if (include_aliases) {
934 Args &path,
bool leaf_is_command,
Status &result) {
937 auto get_multi_or_report_error =
938 [&result](CommandObjectSP cmd_sp,
944 if (!cmd_sp->IsUserCommand()) {
966 if (num_args == 1 && leaf_is_command) {
976 get_multi_or_report_error(cur_cmd_sp, cur_name);
977 if (cur_as_multi ==
nullptr)
980 size_t num_path_elements = num_args - (leaf_is_command ? 1 : 0);
981 for (
size_t cursor = 1; cursor < num_path_elements && cur_as_multi !=
nullptr;
985 cur_as_multi = get_multi_or_report_error(cur_cmd_sp, cur_name);
994 CommandObjectSP command_sp;
996 std::string cmd = std::string(cmd_str);
1001 command_sp = pos->second;
1007 command_sp = alias_pos->second;
1013 command_sp = pos->second;
1019 command_sp = pos->second;
1022 if (!exact && !command_sp) {
1025 CommandObjectSP user_match_sp, user_mw_match_sp, alias_match_sp,
1029 if (matches ==
nullptr)
1030 matches = &local_matches;
1032 unsigned int num_cmd_matches = 0;
1033 unsigned int num_alias_matches = 0;
1034 unsigned int num_user_matches = 0;
1035 unsigned int num_user_mw_matches = 0;
1043 *matches, descriptions);
1046 if (num_cmd_matches == 1) {
1050 real_match_sp = pos->second;
1055 *matches, descriptions);
1058 if (num_alias_matches == 1) {
1062 alias_match_sp = alias_pos->second;
1067 *matches, descriptions);
1070 if (num_user_matches == 1) {
1076 user_match_sp = pos->second;
1084 if (num_user_mw_matches == 1) {
1090 user_mw_match_sp = pos->second;
1096 if (num_user_matches + num_user_mw_matches + num_cmd_matches +
1097 num_alias_matches ==
1099 if (num_cmd_matches)
1100 return real_match_sp;
1101 else if (num_alias_matches)
1102 return alias_match_sp;
1103 else if (num_user_mw_matches)
1104 return user_mw_match_sp;
1106 return user_match_sp;
1108 }
else if (matches && command_sp) {
1118 const lldb::CommandObjectSP &cmd_sp,
1121 lldbassert((
this == &cmd_sp->GetCommandInterpreter()) &&
1122 "tried to add a CommandObject from a different interpreter");
1127 cmd_sp->SetIsUserCommand(
false);
1129 std::string name_sstr(name);
1132 if (!can_replace || !name_iter->second->IsRemovable())
1134 name_iter->second = cmd_sp;
1142 const lldb::CommandObjectSP &cmd_sp,
1146 lldbassert((
this == &cmd_sp->GetCommandInterpreter()) &&
1147 "tried to add a CommandObject from a different interpreter");
1149 result.
SetErrorString(
"can't use the empty string for a command name");
1160 result.
SetErrorString(
"user command exists and force replace not set");
1163 if (cmd_sp->IsMultiwordObject()) {
1166 "can't replace explicitly non-removable multi-word command");
1170 if (!
m_user_dict[std::string(name)]->IsRemovable()) {
1171 result.
SetErrorString(
"can't replace explicitly non-removable command");
1177 cmd_sp->SetIsUserCommand(
true);
1179 if (cmd_sp->IsMultiwordObject())
1188 bool include_aliases)
const {
1190 Args cmd_words(cmd_str);
1192 if (cmd_str.empty())
1200 CommandObjectSP cmd_obj_sp =
1209 for (
size_t i = 1; i < end; ++i) {
1210 if (!cmd_obj_sp->IsMultiwordObject()) {
1233 GetCommandSP(cmd_str,
false,
true, matches, descriptions).get();
1241 command_obj =
GetCommandSP(cmd_str,
true,
true, matches, descriptions).get();
1248 command_obj =
GetCommandSP(cmd_str,
false,
false,
nullptr).get();
1261 return GetCommandSP(cmd_str,
true,
false, matches, descriptions).get();
1266 std::string cmd_str(cmd);
1268 auto found_elem = map.find(std::string(cmd));
1269 if (found_elem == map.end())
1292 StringList *matches_ptr = matches ? matches : &tmp_list;
1295 cmd_str, *matches_ptr);
1305 std::string &full_name)
const {
1309 full_name.assign(std::string(cmd));
1313 size_t num_alias_matches;
1316 if (num_alias_matches == 1) {
1319 const bool include_aliases =
false;
1320 const bool exact =
false;
1321 CommandObjectSP cmd_obj_sp(
1322 GetCommandSP(cmd, include_aliases, exact, ®ular_matches));
1323 if (cmd_obj_sp || regular_matches.
GetSize() > 0)
1348 lldb::CommandObjectSP &command_obj_sp,
1349 llvm::StringRef args_string) {
1350 if (command_obj_sp.get())
1351 lldbassert((
this == &command_obj_sp->GetCommandInterpreter()) &&
1352 "tried to add a CommandObject from a different interpreter");
1354 std::unique_ptr<CommandAlias> command_alias_up(
1355 new CommandAlias(*
this, command_obj_sp, args_string, alias_name));
1357 if (command_alias_up && command_alias_up->IsValid()) {
1359 CommandObjectSP(command_alias_up.get());
1360 return command_alias_up.release();
1378 if (pos->second->IsRemovable()) {
1388 CommandObject::CommandMap::iterator pos =
1398 CommandObject::CommandMap::iterator pos =
1409 llvm::StringRef help_prologue(
GetDebugger().GetIOHandlerHelpPrologue());
1410 if (!help_prologue.empty()) {
1415 CommandObject::CommandMap::const_iterator pos;
1424 (pos->first.compare(0, 1,
"_") == 0))
1428 pos->second->GetHelp(), max_len);
1436 "Current command abbreviations "
1437 "(type '%shelp command alias' for more info):\n",
1445 alias_pos->second->GetHelp(), max_len);
1457 pos->second->GetHelp(), max_len);
1464 result.
AppendMessage(
"Current user-defined container commands:");
1469 pos->second->GetHelp(), max_len);
1475 "For more information on any command, type '%shelp <command-name>'.\n",
1480 llvm::StringRef &command_string) {
1486 size_t start = command_string.find_first_not_of(
k_white_space);
1490 if (start != std::string::npos) {
1493 if (end == std::string::npos)
1494 end = command_string.size();
1495 std::string cmd_word =
1496 std::string(command_string.substr(start, end - start));
1498 if (cmd_obj ==
nullptr)
1508 cmd_obj = sub_cmd_obj;
1520 end >= command_string.size())
1523 start = command_string.find_first_not_of(
k_white_space, end);
1529 command_string = command_string.substr(end);
1534 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
1538 if (pos == std::string::npos)
1547 const size_t s_len = s.size();
1549 while (offset < s_len) {
1550 size_t pos = s.find(
"--", offset);
1551 if (pos == std::string::npos)
1554 if (llvm::isSpace(s[pos - 1])) {
1557 if ((pos + 2 >= s_len) || llvm::isSpace(s[pos + 2])) {
1564 return std::string::npos;
1568 std::string &suffix,
char "e_char) {
1573 bool result =
false;
1576 if (!command_string.empty()) {
1577 const char first_char = command_string[0];
1578 if (first_char ==
'\'' || first_char ==
'"') {
1579 quote_char = first_char;
1580 const size_t end_quote_pos = command_string.find(quote_char, 1);
1581 if (end_quote_pos == std::string::npos) {
1582 command.swap(command_string);
1583 command_string.erase();
1585 command.assign(command_string, 1, end_quote_pos - 1);
1586 if (end_quote_pos + 1 < command_string.size())
1587 command_string.erase(0, command_string.find_first_not_of(
1590 command_string.erase();
1593 const size_t first_space_pos =
1595 if (first_space_pos == std::string::npos) {
1596 command.swap(command_string);
1597 command_string.erase();
1599 command.assign(command_string, 0, first_space_pos);
1600 command_string.erase(0, command_string.find_first_not_of(
1607 if (!command.empty()) {
1609 if (command[0] !=
'-' && command[0] !=
'_') {
1611 if (pos > 0 && pos != std::string::npos) {
1612 suffix.assign(command.begin() + pos, command.end());
1622 llvm::StringRef alias_name, std::string &raw_input_string,
1625 Args cmd_args(raw_input_string);
1629 if (!alias_cmd_obj || !alias_cmd_obj->
IsAlias()) {
1630 alias_result.clear();
1631 return alias_cmd_obj;
1633 std::pair<CommandObjectSP, OptionArgVectorSP> desugared =
1636 alias_cmd_obj = desugared.first.get();
1637 std::string alias_name_str = std::string(alias_name);
1640 cmd_args.
Unshift(alias_name_str);
1644 if (!option_arg_vector_sp.get()) {
1645 alias_result = std::string(result_str.
GetString());
1646 return alias_cmd_obj;
1653 for (
const auto &entry : *option_arg_vector) {
1654 std::tie(option, value_type, value) = entry;
1656 result_str.
Printf(
" %s", value.c_str());
1660 result_str.
Printf(
" %s", option.c_str());
1668 result_str.
Printf(
"%s", value.c_str());
1672 "need at least %d arguments to use "
1678 size_t strpos = raw_input_string.find(entry.
c_str());
1680 if (strpos != std::string::npos) {
1681 const size_t start_fudge = quote_char ==
'\0' ? 0 : 1;
1682 const size_t len_fudge = quote_char ==
'\0' ? 0 : 2;
1685 if (strpos < start_fudge) {
1686 result.
AppendError(
"Unmatched quote at command beginning.");
1689 llvm::StringRef arg_text = entry.
ref();
1690 if (strpos - start_fudge + arg_text.size() + len_fudge
1691 > raw_input_string.size()) {
1692 result.
AppendError(
"Unmatched quote at command end.");
1695 raw_input_string = raw_input_string.erase(
1696 strpos - start_fudge,
1699 if (quote_char ==
'\0')
1702 result_str.
Printf(
"%c%s%c", quote_char,
1703 entry.
c_str(), quote_char);
1707 alias_result = std::string(result_str.
GetString());
1708 return alias_cmd_obj;
1719 size_t start_backtick;
1721 while ((start_backtick = command.find(
'`', pos)) != std::string::npos) {
1726 if (start_backtick > 0 && command[start_backtick - 1] ==
'\\') {
1729 command.erase(start_backtick - 1, 1);
1731 pos = start_backtick;
1735 const size_t expr_content_start = start_backtick + 1;
1736 const size_t end_backtick = command.find(
'`', expr_content_start);
1738 if (end_backtick == std::string::npos) {
1743 if (end_backtick == expr_content_start) {
1745 command.erase(start_backtick, 2);
1749 std::string expr_str(command, expr_content_start,
1750 end_backtick - expr_content_start);
1760 ValueObjectSP expr_result_valobj_sp;
1772 expr_result_valobj_sp, options);
1776 if (expr_result_valobj_sp)
1777 expr_result_valobj_sp =
1778 expr_result_valobj_sp->GetQualifiedRepresentationIfAvailable(
1779 expr_result_valobj_sp->GetDynamicValueType(),
true);
1780 if (expr_result_valobj_sp->ResolveValue(scalar)) {
1781 command.erase(start_backtick, end_backtick - start_backtick + 1);
1783 const bool show_type =
false;
1784 scalar.
GetValue(&value_strm, show_type);
1785 size_t value_string_size = value_strm.
GetSize();
1786 if (value_string_size) {
1787 command.insert(start_backtick, std::string(value_strm.
GetString()));
1788 pos = start_backtick + value_string_size;
1791 error.SetErrorStringWithFormat(
"expression value didn't result "
1792 "in a scalar value for the "
1798 error.SetErrorStringWithFormat(
"expression value didn't result "
1799 "in a scalar value for the "
1808 if (expr_result_valobj_sp)
1809 error = expr_result_valobj_sp->GetError();
1811 if (
error.Success()) {
1812 switch (expr_result) {
1814 error.SetErrorStringWithFormat(
1815 "expression setup error for the expression '%s'", expr_str.c_str());
1818 error.SetErrorStringWithFormat(
1819 "expression parse error for the expression '%s'", expr_str.c_str());
1822 error.SetErrorStringWithFormat(
1823 "expression error fetching result for the expression '%s'",
1829 error.SetErrorStringWithFormat(
1830 "expression discarded for the expression '%s'", expr_str.c_str());
1833 error.SetErrorStringWithFormat(
1834 "expression interrupted for the expression '%s'", expr_str.c_str());
1837 error.SetErrorStringWithFormat(
1838 "expression hit breakpoint for the expression '%s'",
1842 error.SetErrorStringWithFormat(
1843 "expression timed out for the expression '%s'", expr_str.c_str());
1846 error.SetErrorStringWithFormat(
"expression stop at entry point "
1847 "for debugging for the "
1852 error.SetErrorStringWithFormat(
1853 "expression thread vanished for the expression '%s'",
1868 bool status =
HandleCommand(command_line, lazy_add_to_history, result);
1877 std::string command_string(command_line);
1878 std::string original_command_string(command_line);
1881 llvm::PrettyStackTraceFormat stack_trace(
"HandleCommand(command = \"%s\")",
1884 LLDB_LOGF(log,
"Processing command: %s", command_line);
1892 bool add_to_history;
1896 add_to_history = (lazy_add_to_history ==
eLazyBoolYes);
1900 bool empty_command =
false;
1901 bool comment_command =
false;
1902 if (command_string.empty())
1903 empty_command =
true;
1905 const char *k_space_characters =
"\t\n\v\f\r ";
1907 size_t non_space = command_string.find_first_not_of(k_space_characters);
1910 if (non_space == std::string::npos)
1911 empty_command =
true;
1913 comment_command =
true;
1915 llvm::StringRef search_str(command_string);
1916 search_str = search_str.drop_front(non_space);
1918 add_to_history =
false;
1919 command_string = std::string(*hist_str);
1920 original_command_string = std::string(*hist_str);
1923 command_string.c_str());
1929 if (empty_command) {
1941 command_string = command_line;
1942 original_command_string = command_line;
1948 add_to_history =
false;
1949 }
else if (comment_command) {
1989 llvm::StringRef command_name = cmd_obj ? cmd_obj->
GetCommandName() :
"<not found>";
1990 LLDB_LOGF(log,
"HandleCommand, cmd_obj : '%s'", command_name.str().c_str());
1991 LLDB_LOGF(log,
"HandleCommand, (revised) command_string: '%s'",
1992 command_string.c_str());
1993 const bool wants_raw_input =
1995 LLDB_LOGF(log,
"HandleCommand, wants_raw_input:'%s'",
1996 wants_raw_input ?
"True" :
"False");
2004 if (cmd_obj !=
nullptr) {
2008 if (add_to_history || empty_command) {
2009 Args command_args(command_string);
2010 std::optional<std::string> repeat_command =
2021 std::string remainder;
2022 const std::size_t actual_cmd_name_len = cmd_obj->
GetCommandName().size();
2023 if (actual_cmd_name_len < command_string.length())
2024 remainder = command_string.substr(actual_cmd_name_len);
2028 if (pos != 0 && pos != std::string::npos)
2029 remainder.erase(0, pos);
2032 log,
"HandleCommand, command line after removing command name(s): '%s'",
2035 cmd_obj->
Execute(remainder.c_str(), result);
2038 LLDB_LOGF(log,
"HandleCommand, command %s",
2039 (result.
Succeeded() ?
"succeeded" :
"did not succeed"));
2048 bool look_for_subcommand =
false;
2054 bool include_aliases =
true;
2065 &new_matches, &new_descriptions);
2072 look_for_subcommand =
true;
2087 if (command_object) {
2100 if (!first_arg.empty()) {
2105 request.
AddCompletion(*hist_str,
"Previous command history event",
2114std::optional<std::string>
2117 return std::nullopt;
2119 for (
int i = s - 1; i >= 0; --i) {
2121 if (entry.consume_front(line))
2124 return std::nullopt;
2128 EventSP prompt_change_event_sp(
2139 return default_answer;
2143 IOHandlerSP io_handler_sp(confirm);
2172 const char *alias_name,
2174 std::string &raw_input_string,
2182 std::string alias_name_str = alias_name;
2184 cmd_args.
Unshift(alias_name_str);
2190 if (option_arg_vector_sp.get()) {
2191 if (wants_raw_input) {
2195 size_t pos = raw_input_string.find(
" -- ");
2196 if (pos == std::string::npos) {
2198 raw_input_string.insert(0,
" -- ");
2204 std::vector<bool> used(old_size + 1,
false);
2211 for (
const auto &option_entry : *option_arg_vector) {
2212 std::tie(option, value_type, value) = option_entry;
2214 if (!wants_raw_input || (value !=
"--")) {
2238 "need at least %d arguments to use "
2246 if (strpos != std::string::npos) {
2247 raw_input_string = raw_input_string.erase(
2260 for (
auto entry : llvm::enumerate(cmd_args.
entries())) {
2261 if (!used[entry.index()] && !wants_raw_input)
2274 if (wants_raw_input) {
2290 const char *cptr = in_string;
2293 if (cptr[0] ==
'%') {
2297 if (isdigit(cptr[0])) {
2298 const char *start = cptr;
2299 while (isdigit(cptr[0]))
2304 if (cptr[0] ==
'\0')
2305 position = atoi(start);
2313 llvm::StringRef suffix = {}) {
2314 std::string init_file_name =
".lldbinit";
2315 if (!suffix.empty()) {
2316 init_file_name.append(
"-");
2317 init_file_name.append(suffix.str());
2321 llvm::sys::path::append(init_file, init_file_name);
2331 language = *main_repl_language;
2336 std::string init_file_name =
2337 (llvm::Twine(
".lldbinit-") +
2339 llvm::Twine(
"-repl"))
2342 llvm::sys::path::append(init_file, init_file_name);
2347 llvm::StringRef s =
".lldbinit";
2348 init_file.assign(s.begin(), s.end());
2380 llvm::SmallString<128> init_file;
2390 switch (should_load) {
2398 llvm::SmallString<128> home_init_file;
2400 if (llvm::sys::path::parent_path(init_file) ==
2401 llvm::sys::path::parent_path(home_init_file)) {
2421 llvm::SmallString<128> init_file;
2426 if (init_file.empty())
2430 llvm::StringRef program_name =
2431 HostInfo::GetProgramFileSpec().GetFilename().GetStringRef();
2432 llvm::SmallString<128> program_init_file;
2435 init_file = program_init_file;
2442#ifdef LLDB_GLOBAL_INIT_DIRECTORY
2444 FileSpec init_file(LLDB_GLOBAL_INIT_DIRECTORY);
2458 return prefix ==
nullptr ?
"" : prefix;
2462 PlatformSP platform_sp;
2463 if (prefer_target_platform) {
2477 TargetSP target_sp = exe_ctx.GetTargetSP();
2481 ProcessSP process_sp(target_sp->GetProcessSP());
2488 for (
const auto &thread_sp : process_sp->GetThreadList().Threads()) {
2489 StopInfoSP stop_info = thread_sp->GetStopInfo();
2497 const StopReason reason = stop_info->GetStopReason();
2504 const auto stop_signal =
static_cast<int32_t
>(stop_info->GetValue());
2505 UnixSignalsSP signals_sp = process_sp->GetUnixSignals();
2506 if (!signals_sp || !signals_sp->SignalIsValid(stop_signal))
2510 const auto sigint_num = signals_sp->GetSignalNumberFromName(
"SIGINT");
2511 const auto sigstop_num = signals_sp->GetSignalNumberFromName(
"SIGSTOP");
2512 if ((stop_signal != sigint_num) && (stop_signal != sigstop_num))
2535 size_t num_lines = commands.
GetSize();
2547 for (
size_t idx = 0; idx < num_lines && !
WasInterrupted(); idx++) {
2576 if (!success || !tmp_result.
Succeeded()) {
2578 if (error_msg.empty())
2579 error_msg =
"<unknown error>.\n";
2582 "Aborting reading of commands after command #%" PRIu64
2583 ": '%s' failed with %s",
2584 (uint64_t)idx, cmd, error_msg.str().c_str());
2589 "Command #%" PRIu64
" '%s' failed with %s", (uint64_t)idx + 1, cmd,
2590 error_msg.str().c_str());
2611 if (idx != num_lines - 1)
2613 "Aborting reading of commands after command #%" PRIu64
2614 ": '%s' continued the target.\n",
2615 (uint64_t)idx + 1, cmd);
2618 " '%s' continued the target.\n",
2619 (uint64_t)idx + 1, cmd);
2631 if (idx != num_lines - 1)
2633 "Aborting reading of commands after command #%" PRIu64
2634 ": '%s' stopped with a signal or exception.\n",
2635 (uint64_t)idx + 1, cmd);
2638 "Command #%" PRIu64
" '%s' stopped with a signal or exception.\n",
2639 (uint64_t)idx + 1, cmd);
2676 "Error reading commands from file %s - file not found.\n",
2681 std::string cmd_file_path = cmd_file.
GetPath();
2682 auto input_file_up =
2684 if (!input_file_up) {
2685 std::string
error = llvm::toString(input_file_up.takeError());
2687 "error: an error occurred read file '{0}': {1}\n", cmd_file_path,
2688 llvm::fmt_consume(input_file_up.takeError()));
2691 FileSP input_file_sp = FileSP(std::move(input_file_up.get()));
2778 cmd_file_path.c_str());
2783 lldb::StreamFileSP empty_stream_sp;
2794 debugger.
GetPrompt(), llvm::StringRef(),
2824 llvm::StringRef prefix,
2825 llvm::StringRef help_text) {
2828 size_t line_width_max = max_columns - prefix.size();
2829 if (line_width_max < 16)
2830 line_width_max = help_text.size() + prefix.size();
2833 bool prefixed_yet =
false;
2835 if (help_text.empty())
2836 help_text =
"No help text";
2837 while (!help_text.empty()) {
2839 if (!prefixed_yet) {
2841 prefixed_yet =
true;
2846 llvm::StringRef this_line = help_text.substr(0, line_width_max);
2849 std::size_t first_newline = this_line.find_first_of(
"\n");
2852 std::size_t last_space = llvm::StringRef::npos;
2853 if (this_line.size() != help_text.size())
2854 last_space = this_line.find_last_of(
" \t");
2857 this_line = this_line.substr(0, std::min(first_newline, last_space));
2862 help_text = help_text.drop_front(this_line.size()).ltrim();
2868 llvm::StringRef word_text,
2869 llvm::StringRef separator,
2870 llvm::StringRef help_text,
2871 size_t max_word_len) {
2873 prefix_stream.
Printf(
" %-*s %*s ", (
int)max_word_len, word_text.data(),
2874 (
int)separator.size(), separator.data());
2879 llvm::StringRef separator,
2880 llvm::StringRef help_text,
2882 int indent_size = max_word_len + separator.size() + 2;
2887 text_strm.
Printf(
"%-*s ", (
int)max_word_len, word_text.data());
2888 text_strm << separator <<
" " << help_text;
2892 llvm::StringRef text = text_strm.
GetString();
2896 auto nextWordLength = [](llvm::StringRef S) {
2897 size_t pos = S.find(
' ');
2898 return pos == llvm::StringRef::npos ? S.size() : pos;
2901 while (!text.empty()) {
2902 if (text.front() ==
'\n' ||
2903 (text.front() ==
' ' && nextWordLength(text.ltrim(
' ')) > chars_left)) {
2906 chars_left = max_columns - indent_size;
2907 if (text.front() ==
'\n')
2908 text = text.drop_front();
2910 text = text.ltrim(
' ');
2914 text = text.drop_front();
2923 llvm::StringRef search_word,
StringList &commands_found,
2925 for (
const auto &pair : command_map) {
2926 llvm::StringRef command_name = pair.first;
2929 const bool search_short_help =
true;
2930 const bool search_long_help =
false;
2931 const bool search_syntax =
false;
2932 const bool search_options =
false;
2933 if (command_name.contains_insensitive(search_word) ||
2935 search_long_help, search_syntax,
2944 multiword_cmd->GetSubcommandDictionary());
2945 for (
const auto &subcommand_name : subcommands_found) {
2946 std::string qualified_name =
2947 (command_name +
" " + subcommand_name).str();
2957 bool search_builtin_commands,
2958 bool search_user_commands,
2959 bool search_alias_commands,
2960 bool search_user_mw_commands) {
2961 CommandObject::CommandMap::const_iterator pos;
2963 if (search_builtin_commands)
2967 if (search_user_commands)
2971 if (search_user_mw_commands)
2975 if (search_alias_commands)
3027 bool was_interrupted =
3030 return was_interrupted;
3034 llvm::StringRef str,
3041 llvm::StringRef line;
3042 std::tie(line, str) = str.split(
'\n');
3044 std::lock_guard<std::recursive_mutex> guard(io_handler.
GetOutputMutex());
3045 stream->Write(line.data(), line.size());
3046 stream->Write(
"\n", 1);
3050 std::lock_guard<std::recursive_mutex> guard(io_handler.
GetOutputMutex());
3052 stream->Printf(
"\n... Interrupted.\n");
3057 llvm::StringRef line,
const Flags &io_handler_flags)
const {
3061 llvm::StringRef command = line.trim();
3062 if (command.empty())
3072 std::string &line) {
3078 if (!is_interactive) {
3090 std::lock_guard<std::recursive_mutex> guard(io_handler.
GetOutputMutex());
3092 "%s%s\n", io_handler.
GetPrompt(), line.c_str());
3099 bool pushed_exe_ctx =
false;
3102 pushed_exe_ctx =
true;
3104 auto finalize = llvm::make_scope_exit([
this, pushed_exe_ctx]() {
3113 if ((result.Succeeded() &&
3119 if (!result.GetImmediateOutputStream()) {
3120 llvm::StringRef output = result.GetOutputData();
3125 if (!result.GetImmediateErrorStream()) {
3126 llvm::StringRef
error = result.GetErrorData();
3133 switch (result.GetStatus()) {
3162 result.GetDidChangeProcessState() &&
3187 if (script_interpreter) {
3196 if (output_file == std::nullopt || output_file->empty()) {
3197 std::string now = llvm::to_string(std::chrono::system_clock::now());
3198 std::replace(now.begin(), now.end(),
' ',
'_');
3199 const std::string file_name =
"lldb_session_" + now +
".log";
3204 save_location = HostInfo::GetGlobalTempDir();
3208 output_file = save_location.
GetPath();
3211 auto error_out = [&](llvm::StringRef error_message, std::string description) {
3213 output_file, description);
3215 "Failed to save session's transcripts to {0}!", *output_file);
3226 return error_out(
"Unable to create file",
3227 llvm::toString(opened_file.takeError()));
3229 FileUP file = std::move(opened_file.get());
3236 return error_out(
"Unable to write to destination file",
3237 "Bytes written do not match transcript size.");
3241 output_file->c_str());
3245 error = file->GetFileSpec(
const_cast<FileSpec &
>(file_spec));
3246 if (
error.Success())
3266 IOHandlerSP io_handler_sp(
3269 llvm::StringRef(prompt),
3276 if (io_handler_sp) {
3277 io_handler_sp->SetUserData(baton);
3285 IOHandlerSP io_handler_sp(
3288 llvm::StringRef(prompt),
3295 if (io_handler_sp) {
3296 io_handler_sp->SetUserData(baton);
3354 bool force_create =
true;
3376 std::string scratch_command(command_line);
3380 bool wants_raw_input =
false;
3381 std::string next_word;
3385 char quote_char =
'\0';
3388 if (cmd_obj ==
nullptr) {
3389 std::string full_name;
3392 bool is_real_command =
3393 (!is_alias) || (cmd_obj !=
nullptr && !cmd_obj->
IsAlias());
3394 if (!is_real_command) {
3396 std::string alias_result;
3399 revised_command_line.
Printf(
"%s", alias_result.c_str());
3406 revised_command_line.
Printf(
"%s", cmd_name.str().c_str());
3409 revised_command_line.
Printf(
"%s", next_word.c_str());
3420 revised_command_line.
Clear();
3421 revised_command_line.
Printf(
"%s", sub_cmd_name.str().c_str());
3422 cmd_obj = sub_cmd_obj;
3426 revised_command_line.
Printf(
" %c%s%s%c", quote_char,
3427 next_word.c_str(), suffix.c_str(),
3430 revised_command_line.
Printf(
" %s%s", next_word.c_str(),
3436 revised_command_line.
Printf(
" %c%s%s%c", quote_char,
3437 next_word.c_str(), suffix.c_str(),
3440 revised_command_line.
Printf(
" %s%s", next_word.c_str(),
3446 if (cmd_obj ==
nullptr) {
3447 const size_t num_matches = matches.
GetSize();
3450 error_msg.
Printf(
"Ambiguous command '%s'. Possible matches:\n",
3453 for (
uint32_t i = 0; i < num_matches; ++i) {
3467 if (!suffix.empty()) {
3469 "command '%s' did not recognize '%s%s%s' as valid (subcommand "
3470 "might be invalid).\n",
3472 next_word.empty() ?
"" : next_word.c_str(),
3473 next_word.empty() ?
" -- " :
" ", suffix.c_str());
3479 if (!suffix.empty()) {
3480 switch (suffix[0]) {
3485 if (command_options &&
3487 std::string gdb_format_option(
"--gdb-format=");
3488 gdb_format_option += (suffix.c_str() + 1);
3490 std::string cmd = std::string(revised_command_line.
GetString());
3492 if (arg_terminator_idx != std::string::npos) {
3495 gdb_format_option.append(1,
' ');
3496 cmd.insert(arg_terminator_idx, gdb_format_option);
3497 revised_command_line.
Clear();
3500 revised_command_line.
Printf(
" %s", gdb_format_option.c_str());
3502 if (wants_raw_input &&
3507 "the '%s' command doesn't support the --gdb-format option\n",
3516 "unknown command shorthand suffix: '%s'\n", suffix.c_str());
3521 if (scratch_command.empty())
3525 if (!scratch_command.empty())
3526 revised_command_line.
Printf(
" %s", scratch_command.c_str());
3528 if (cmd_obj !=
nullptr)
3529 command_line = std::string(revised_command_line.
GetString());
static const char * k_valid_command_chars
static constexpr const char * InitFileWarning
static size_t FindArgumentTerminator(const std::string &s)
#define REGISTER_COMMAND_OBJECT(NAME, CLASS)
static void StripLeadingSpaces(std::string &s)
static void GetHomeREPLInitFile(llvm::SmallVectorImpl< char > &init_file, LanguageType language)
static void GetCwdInitFile(llvm::SmallVectorImpl< char > &init_file)
static const char * k_white_space
static void GetHomeInitFile(llvm::SmallVectorImpl< char > &init_file, llvm::StringRef suffix={})
static bool ExtractCommand(std::string &command_string, std::string &command, std::string &suffix, char "e_char)
@ eHandleCommandFlagStopOnCrash
@ eHandleCommandFlagEchoCommentCommand
@ eHandleCommandFlagStopOnError
@ eHandleCommandFlagStopOnContinue
@ eHandleCommandFlagPrintErrors
@ eHandleCommandFlagEchoCommand
@ eHandleCommandFlagPrintResult
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
#define LLDB_LOGF(log,...)
#define LLDB_SCOPED_TIMER()
#define LLDB_SCOPED_TIMERF(...)
A command line argument class.
void Unshift(llvm::StringRef arg_str, char quote_char='\0')
Inserts a class owned copy of arg_str at the beginning of the argument vector.
void Shift()
Shifts the first argument C string value of the array off the argument array.
void SetArguments(size_t argc, const char **argv)
Sets the argument vector value, optionally copying all arguments into an internal buffer.
size_t GetArgumentCount() const
Gets the number of arguments left in this command object.
void AppendArgument(llvm::StringRef arg_str, char quote_char='\0')
Appends a new argument to the end of the list argument list.
llvm::ArrayRef< ArgEntry > entries() const
const char * GetArgumentAtIndex(size_t idx) const
Gets the NULL terminated C string argument pointer for the argument at index idx.
const char ** GetConstArgumentVector() const
Gets the argument vector.
void Clear()
Clear the arguments.
An event broadcasting class.
void SetEventName(uint32_t event_mask, const char *name)
Set the name for an event bit.
void BroadcastEvent(lldb::EventSP &event_sp)
Broadcast an event which has no associated data.
void CheckInWithManager()
OptionArgVectorSP GetOptionArguments() const
void SetHelp(llvm::StringRef str) override
void SetHelpLong(llvm::StringRef str) override
std::optional< llvm::StringRef > FindString(llvm::StringRef input_str) const
static const char g_repeat_char
llvm::StringRef GetStringAtIndex(size_t idx) const
void AppendString(llvm::StringRef str, bool reject_if_dupe=true)
bool GetSpawnThread() const
void SetStopOnContinue(bool stop_on_continue)
void SetSilent(bool silent)
bool GetAutoHandleEvents() const
void SetPrintErrors(bool print_errors)
LazyBool m_add_to_history
bool GetStopOnCrash() const
bool GetAddToHistory() const
bool GetStopOnContinue() const
bool GetPrintResults() const
void SetStopOnError(bool stop_on_error)
bool GetStopOnError() const
bool GetEchoCommands() const
LazyBool m_echo_comment_commands
LazyBool m_stop_on_continue
bool IsResult(lldb::CommandInterpreterResult result)
void SetResult(lldb::CommandInterpreterResult result)
void IncrementNumberOfErrors()
bool m_skip_lldbinit_files
bool EchoCommandNonInteractive(llvm::StringRef line, const Flags &io_handler_flags) const
void UpdatePrompt(llvm::StringRef prompt)
bool IOHandlerInterrupt(IOHandler &io_handler) override
lldb::IOHandlerSP m_command_io_handler_sp
void SetPromptOnQuit(bool enable)
void SourceInitFileHome(CommandReturnObject &result, bool is_repl)
We will first see if there is an application specific ".lldbinit" file whose name is "~/....
std::optional< std::string > GetAutoSuggestionForCommand(llvm::StringRef line)
Returns the auto-suggestion string that should be added to the given command line.
void IOHandlerInputComplete(IOHandler &io_handler, std::string &line) override
Called when a line or lines have been retrieved.
void LoadCommandDictionary()
std::stack< ExecutionContext > m_overriden_exe_contexts
bool GetStopCmdSourceOnError() const
void OutputFormattedHelpText(Stream &strm, llvm::StringRef prefix, llvm::StringRef help_text)
bool Confirm(llvm::StringRef message, bool default_answer)
bool UserMultiwordCommandExists(llvm::StringRef cmd) const
Determine whether a root-level user multiword command with this name exists.
static const char * g_no_argument
void SetEchoCommands(bool enable)
bool RemoveAlias(llvm::StringRef alias_name)
void SetSaveSessionDirectory(llvm::StringRef path)
bool HasAliasOptions() const
void SourceInitFile(FileSpec file, CommandReturnObject &result)
CommandAlias * AddAlias(llvm::StringRef alias_name, lldb::CommandObjectSP &command_obj_sp, llvm::StringRef args_string=llvm::StringRef())
int GetCommandNamesMatchingPartialString(const char *cmd_cstr, bool include_aliases, StringList &matches, StringList &descriptions)
void FindCommandsForApropos(llvm::StringRef word, StringList &commands_found, StringList &commands_help, bool search_builtin_commands, bool search_user_commands, bool search_alias_commands, bool search_user_mw_commands)
CommandObject * GetCommandObject(llvm::StringRef cmd, StringList *matches=nullptr, StringList *descriptions=nullptr) const
std::atomic< CommandHandlingState > m_command_state
Status PreprocessCommand(std::string &command)
CommandObject::CommandMap m_alias_dict
CommandObject * ResolveCommandImpl(std::string &command_line, CommandReturnObject &result)
CommandObject::CommandMap m_command_dict
void SetOpenTranscriptInEditor(bool enable)
void HandleCompletion(CompletionRequest &request)
CommandInterpreterRunResult m_result
bool GetSpaceReplPrompts() const
void ResolveCommand(const char *command_line, CommandReturnObject &result)
bool SetQuitExitCode(int exit_code)
Sets the exit code for the quit command.
CommandInterpreterRunResult RunCommandInterpreter(CommandInterpreterRunOptions &options)
bool HandleCommand(const char *command_line, LazyBool add_to_history, const ExecutionContext &override_context, CommandReturnObject &result)
bool DidProcessStopAbnormally() const
CommandObject::CommandMap m_user_dict
std::optional< int > m_quit_exit_code
ExecutionContext GetExecutionContext() const
const CommandObject::CommandMap & GetUserCommands() const
CommandObject * GetUserCommandObject(llvm::StringRef cmd, StringList *matches=nullptr, StringList *descriptions=nullptr) const
void SourceInitFileGlobal(CommandReturnObject &result)
bool GetAliasFullName(llvm::StringRef cmd, std::string &full_name) const
CommandObjectMultiword * VerifyUserMultiwordCmdPath(Args &path, bool leaf_is_command, Status &result)
Look up the command pointed to by path encoded in the arguments of the incoming command object.
bool GetEchoCommentCommands() const
bool WasInterrupted() const
void HandleCompletionMatches(CompletionRequest &request)
Status AddUserCommand(llvm::StringRef name, const lldb::CommandObjectSP &cmd_sp, bool can_replace)
bool AddCommand(llvm::StringRef name, const lldb::CommandObjectSP &cmd_sp, bool can_replace)
void PrintCommandOutput(IOHandler &io_handler, llvm::StringRef str, bool is_stdout)
int m_iohandler_nesting_level
bool GetOpenTranscriptInEditor() const
bool AliasExists(llvm::StringRef cmd) const
Determine whether an alias command with this name exists.
bool GetExpandRegexAliases() const
int GetOptionArgumentPosition(const char *in_string)
Picks the number out of a string of the form "%NNN", otherwise return 0.
bool HasUserMultiwordCommands() const
void StartHandlingCommand()
void GetHelp(CommandReturnObject &result, uint32_t types=eCommandTypesAllThem)
bool CommandExists(llvm::StringRef cmd) const
Determine whether a root level, built-in command with this name exists.
bool GetPromptOnQuit() const
std::string m_repeat_command
static ConstString & GetStaticBroadcasterClass()
const char * GetCommandPrefix()
bool SaveTranscript(CommandReturnObject &result, std::optional< std::string > output_file=std::nullopt)
Save the current debugger session transcript to a file on disk.
int GetQuitExitCode(bool &exited) const
Returns the exit code that the user has specified when running the 'quit' command.
lldb::PlatformSP GetPlatform(bool prefer_target_platform)
bool GetRequireCommandOverwrite() const
void RestoreExecutionContext()
void GetPythonCommandsFromIOHandler(const char *prompt, IOHandlerDelegate &delegate, void *baton=nullptr)
lldb::CommandObjectSP GetCommandSPExact(llvm::StringRef cmd, bool include_aliases=false) const
@ eBroadcastBitQuitCommandReceived
@ eBroadcastBitResetPrompt
@ eBroadcastBitThreadShouldExit
CommandInterpreter(Debugger &debugger, bool synchronous_execution)
const CommandAlias * GetAlias(llvm::StringRef alias_name) const
void FinishHandlingCommand()
bool RemoveUser(llvm::StringRef alias_name)
void GetLLDBCommandsFromIOHandler(const char *prompt, IOHandlerDelegate &delegate, void *baton=nullptr)
lldb::CommandObjectSP GetCommandSP(llvm::StringRef cmd, bool include_aliases=true, bool exact=true, StringList *matches=nullptr, StringList *descriptions=nullptr) const
void OutputHelpText(Stream &stream, llvm::StringRef command_word, llvm::StringRef separator, llvm::StringRef help_text, uint32_t max_word_len)
CommandObject * GetCommandObjectForCommand(llvm::StringRef &command_line)
static const char * g_need_argument
bool m_skip_app_init_files
void SetSynchronous(bool value)
uint32_t m_command_source_depth
bool RemoveUserMultiword(llvm::StringRef multiword_name)
bool GetSaveSessionOnQuit() const
FileSpec GetSaveSessionDirectory() const
bool UserCommandExists(llvm::StringRef cmd) const
Determine whether a root-level user command with this name exists.
bool GetRepeatPreviousCommand() const
lldb::IOHandlerSP GetIOHandler(bool force_create=false, CommandInterpreterRunOptions *options=nullptr)
bool HasUserCommands() const
const CommandObject::CommandMap & GetUserMultiwordCommands() const
void BuildAliasCommandArgs(CommandObject *alias_cmd_obj, const char *alias_name, Args &cmd_args, std::string &raw_input_string, CommandReturnObject &result)
std::vector< uint32_t > m_command_source_flags
CommandHistory m_command_history
CommandObject * BuildAliasResult(llvm::StringRef alias_name, std::string &raw_input_string, std::string &alias_result, CommandReturnObject &result)
void OverrideExecutionContext(const ExecutionContext &override_context)
bool SetBatchCommandMode(bool value)
const char * ProcessEmbeddedScriptCommands(const char *arg)
void AllowExitCodeOnQuit(bool allow)
Specify if the command interpreter should allow that the user can specify a custom exit code when cal...
CommandObject::CommandMap m_user_mw_dict
bool m_synchronous_execution
StreamString m_transcript_stream
void HandleCommandsFromFile(FileSpec &file, const ExecutionContext &context, const CommandInterpreterRunOptions &options, CommandReturnObject &result)
Execute a list of commands from a file.
void SourceInitFileCwd(CommandReturnObject &result)
void SetSaveSessionOnQuit(bool enable)
static const char * g_argument
std::vector< FileSpec > m_command_source_dirs
A stack of directory paths.
void HandleCommands(const StringList &commands, const ExecutionContext &context, const CommandInterpreterRunOptions &options, CommandReturnObject &result)
Execute a list of commands in sequence.
bool RemoveCommand(llvm::StringRef cmd)
FileSpec GetCurrentSourceDir()
void SetEchoCommentCommands(bool enable)
bool GetEchoCommands() const
Implements dwim-print, a printing command that chooses the most direct, efficient,...
lldb::CommandObjectSP GetSubcommandSPExact(llvm::StringRef sub_cmd) override
CommandObjectMultiword * GetAsMultiwordCommand() override
virtual bool WantsRawCommandString()=0
llvm::StringRef GetCommandName() const
bool HelpTextContainsWord(llvm::StringRef search_word, bool search_short_help=true, bool search_long_help=true, bool search_syntax=true, bool search_options=true)
virtual bool IsMultiwordObject()
virtual std::optional< std::string > GetRepeatCommand(Args ¤t_command_args, uint32_t index)
Get the command that appropriate for a "repeat" of the current command.
virtual CommandObject * GetSubcommandObject(llvm::StringRef sub_cmd, StringList *matches=nullptr)
virtual bool Execute(const char *args_string, CommandReturnObject &result)=0
virtual CommandObjectMultiword * GetAsMultiwordCommand()
virtual Options * GetOptions()
void SetSyntax(llvm::StringRef str)
virtual void HandleCompletion(CompletionRequest &request)
This default version handles calling option argument completions and then calls HandleArgumentComplet...
std::map< std::string, lldb::CommandObjectSP > CommandMap
virtual llvm::StringRef GetHelp()
void AppendErrorWithFormatv(const char *format, Args &&... args)
void AppendMessage(llvm::StringRef in_string)
bool GetInteractive() const
void void AppendError(llvm::StringRef in_string)
lldb::StreamSP GetImmediateOutputStream()
bool GetDidChangeProcessState() const
void SetSuppressImmediateOutput(bool b)
llvm::StringRef GetErrorData()
void SetInteractive(bool b)
void AppendRawError(llvm::StringRef in_string)
llvm::StringRef GetOutputData()
void SetStatus(lldb::ReturnStatus status)
void AppendErrorWithFormat(const char *format,...) __attribute__((format(printf
void AppendMessageWithFormat(const char *format,...) __attribute__((format(printf
lldb::StreamSP GetImmediateErrorStream()
lldb::ReturnStatus GetStatus() const
Stream & GetOutputStream()
"lldb/Utility/ArgCompletionRequest.h"
void AddCompletion(llvm::StringRef completion, llvm::StringRef description="", CompletionMode mode=CompletionMode::Normal)
Adds a possible completion string.
void AddCompletions(const StringList &completions)
Adds multiple possible completion strings.
const Args & GetParsedLine() const
void ShiftArguments()
Drops the first argument from the argument list.
void AppendEmptyArgument()
Adds an empty argument at the end of the argument list and moves the cursor to this new argument.
size_t GetCursorIndex() const
A uniqued constant string class.
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
A class to manage flag bits.
ExecutionContext GetSelectedExecutionContext()
bool StartEventHandlerThread()
void StopEventHandlerThread()
void SetAsyncExecution(bool async)
lldb::FileSP GetInputFileSP()
bool StartIOHandlerThread()
bool IsTopIOHandler(const lldb::IOHandlerSP &reader_sp)
const char * GetIOHandlerCommandPrefix()
void RunIOHandlerAsync(const lldb::IOHandlerSP &reader_sp, bool cancel_top_handler=true)
Run the given IO handler and return immediately.
lldb::StreamFileSP GetErrorStreamSP()
uint32_t GetTerminalWidth() const
bool GetAutoConfirm() const
PlatformList & GetPlatformList()
Target & GetDummyTarget()
void RunIOHandlerSync(const lldb::IOHandlerSP &reader_sp)
Run the given IO handler and block until it's complete.
lldb::StreamFileSP GetOutputStreamSP()
ScriptInterpreter * GetScriptInterpreter(bool can_create=true, std::optional< lldb::ScriptLanguage > language={})
llvm::StringRef GetPrompt() const
void FlushProcessOutput(Process &process, bool flush_stdout, bool flush_stderr)
void SetUnwindOnError(bool unwind=false)
void SetKeepInMemory(bool keep=true)
void SetCoerceToId(bool coerce=true)
void SetTryAllThreads(bool try_others=true)
void SetTimeout(const Timeout< std::micro > &timeout)
void SetIgnoreBreakpoints(bool ignore=false)
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
StackFrame * GetFramePtr() const
Returns a pointer to the frame object.
Target * GetTargetPtr() const
Returns a pointer to the target object.
bool HasTargetScope() const
Returns true the ExecutionContext object contains a valid target.
Process * GetProcessPtr() const
Returns a pointer to the process object.
void AppendPathComponent(llvm::StringRef component)
const ConstString & GetFilename() const
Filename string const get accessor.
void MakeAbsolute(const FileSpec &dir)
Make the FileSpec absolute by treating it relative to dir.
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
FileSpec CopyByRemovingLastPathComponent() const
void Resolve(llvm::SmallVectorImpl< char > &path)
Resolve path to make it canonical.
bool GetHomeDirectory(llvm::SmallVectorImpl< char > &path) const
Get the user home directory.
int Open(const char *path, int flags, int mode)
Wraps ::open in a platform-independent way.
static FileSystem & Instance()
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
bool Test(ValueType bit) const
Test a single flag bit.
static bool OpenFileInExternalEditor(const FileSpec &file_spec, uint32_t line_no)
static bool IsInteractiveGraphicSession()
Check if we're running in an interactive graphical session.
A delegate class for use with IOHandler subclasses.
lldb::StreamFileSP GetErrorStreamFileSP()
virtual const char * GetPrompt()
std::recursive_mutex & GetOutputMutex()
lldb::StreamFileSP GetOutputStreamFileSP()
bool GetIsInteractive()
Check if the input is being supplied interactively by a user.
static LanguageSet GetLanguagesSupportingREPLs()
static const char * GetNameForLanguageType(lldb::LanguageType language)
A command line option parsing protocol class.
bool SupportsLongOption(const char *long_option)
A plug-in interface definition class for debugging a process.
lldb::StateType GetState()
Get accessor for the current process state.
Status Halt(bool clear_thread_plans=false, bool use_run_lock=true)
Halts a running process.
lldb::OptionValuePropertiesSP m_collection_sp
void GetValue(Stream *s, bool show_type) const
void Clear()
Clear the object state.
int SetErrorStringWithFormat(const char *format,...) __attribute__((format(printf
Set the current error string to a formatted error string.
void SetErrorString(llvm::StringRef err_str)
Set the current error string to err_str.
const char * GetData() const
llvm::StringRef GetString() const
A stream class that can stream formatted output to a file.
size_t Indent(llvm::StringRef s="")
Indent the current line in the stream.
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
size_t EOL()
Output and End of Line character to the stream.
void IndentLess(unsigned amount=2)
Decrement the current indentation level.
void IndentMore(unsigned amount=2)
Increment the current indentation level.
void AppendString(const std::string &s)
const char * GetStringAtIndex(size_t idx) const
void DeleteStringAtIndex(size_t id)
LoadCWDlldbinitFile GetLoadCWDlldbinitFile() const
static TargetProperties & GetGlobalProperties()
lldb::PlatformSP GetPlatform()
lldb::ExpressionResults EvaluateExpression(llvm::StringRef expression, ExecutionContextScope *exe_scope, lldb::ValueObjectSP &result_valobj_sp, const EvaluateExpressionOptions &options=EvaluateExpressionOptions(), std::string *fixed_expression=nullptr, ValueObject *ctx_obj=nullptr)
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
int AddNamesMatchingPartialString(const std::map< std::string, ValueType > &in_map, llvm::StringRef cmd_str, StringList &matches, StringList *descriptions=nullptr)
std::shared_ptr< OptionArgVector > OptionArgVectorSP
bool StateIsRunningState(lldb::StateType state)
Check if a state represents a state where the process or thread is running.
size_t FindLongestCommandWord(std::map< std::string, ValueType > &dict)
@ RewriteLine
The full line has been rewritten by the completion.
std::vector< std::tuple< std::string, int, std::string > > OptionArgVector
@ eCommandInterpreterResultInferiorCrash
Stopped because the corresponding option was set and the inferior crashed.
@ eCommandInterpreterResultSuccess
Command interpreter finished successfully.
@ eCommandInterpreterResultCommandError
Stopped because the corresponding option was set and a command returned an error.
@ eCommandInterpreterResultQuitRequested
Stopped because quit was requested.
StateType
Process and Thread States.
@ eStateStopped
Process or thread is stopped and can be examined.
LanguageType
Programming language type.
@ eLanguageTypeUnknown
Unknown or invalid language value.
ExpressionResults
The results of expression evaluation.
@ eExpressionHitBreakpoint
@ eExpressionStoppedForDebug
@ eExpressionResultUnavailable
@ eExpressionThreadVanished
@ eReturnStatusSuccessContinuingResult
@ eReturnStatusSuccessContinuingNoResult
@ eReturnStatusSuccessFinishResult
@ eReturnStatusSuccessFinishNoResult
StopReason
Thread stop reasons.
@ eStopReasonInstrumentation
@ eStopReasonProcessorTrace
const char * c_str() const
llvm::StringRef ref() const
char GetQuoteChar() const
A SmallBitVector that represents a set of source languages (lldb::LanguageType).
std::optional< lldb::LanguageType > GetSingularLanguage()
If the set contains a single language only, return it.