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;
149 return GetPropertyAtIndexAs<bool>(
150 idx, g_interpreter_properties[idx].default_uint_value != 0);
154 const uint32_t idx = ePropertyPromptOnQuit;
155 return GetPropertyAtIndexAs<bool>(
156 idx, g_interpreter_properties[idx].default_uint_value != 0);
160 const uint32_t idx = ePropertyPromptOnQuit;
165 const uint32_t idx = ePropertySaveSessionOnQuit;
166 return GetPropertyAtIndexAs<bool>(
167 idx, g_interpreter_properties[idx].default_uint_value != 0);
171 const uint32_t idx = ePropertySaveSessionOnQuit;
176 const uint32_t idx = ePropertyOpenTranscriptInEditor;
177 return GetPropertyAtIndexAs<bool>(
178 idx, g_interpreter_properties[idx].default_uint_value != 0);
182 const uint32_t idx = ePropertyOpenTranscriptInEditor;
187 const uint32_t idx = ePropertySaveSessionDirectory;
188 return GetPropertyAtIndexAs<FileSpec>(idx, {});
192 const uint32_t idx = ePropertySaveSessionDirectory;
197 const uint32_t idx = ePropertyEchoCommands;
198 return GetPropertyAtIndexAs<bool>(
199 idx, g_interpreter_properties[idx].default_uint_value != 0);
203 const uint32_t idx = ePropertyEchoCommands;
208 const uint32_t idx = ePropertyEchoCommentCommands;
209 return GetPropertyAtIndexAs<bool>(
210 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;
249 return GetPropertyAtIndexAs<bool>(
250 idx, g_interpreter_properties[idx].default_uint_value != 0);
254 const uint32_t idx = ePropertySpaceReplPrompts;
255 return GetPropertyAtIndexAs<bool>(
256 idx, g_interpreter_properties[idx].default_uint_value != 0);
260 const uint32_t idx = ePropertyRepeatPreviousCommand;
261 return GetPropertyAtIndexAs<bool>(
262 idx, g_interpreter_properties[idx].default_uint_value != 0);
266 const uint32_t idx = ePropertyRequireCommandOverwrite;
267 return GetPropertyAtIndexAs<bool>(
268 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>();
420 if (
auto *po =
AddAlias(
"po", cmd_obj_sp,
"-O --")) {
421 po->SetHelp(
"Evaluate an expression on the current thread. Displays any "
422 "returned value with formatting "
423 "controlled by the type's author.");
432 AddAlias(
"parray", cmd_obj_sp,
"--element-count %1 --");
435 (
"parray <COUNT> <EXPRESSION> -- lldb will evaluate EXPRESSION "
436 "to get a typed-pointer-to-an-array in memory, and will display "
437 "COUNT elements of that type from the array.");
441 "--object-description --element-count %1 --");
443 poarray_alias->
SetHelp(
"poarray <COUNT> <EXPRESSION> -- lldb will "
444 "evaluate EXPRESSION to get the address of an array of COUNT "
445 "objects in memory, and will call po on them.");
454 shell_alias->
SetHelp(
"Run a shell command on the host.");
456 shell_alias->
SetSyntax(
"shell <shell-command>");
467 alias_arguments_vector_sp = std::make_shared<OptionArgVector>();
468#if defined(__APPLE__)
473 AddAlias(
"r", cmd_obj_sp,
"--shell-expand-args true --");
474 AddAlias(
"run", cmd_obj_sp,
"--shell-expand-args true --");
478 defaultshell.
Printf(
"--shell=%s --",
479 HostInfo::GetDefaultShell().GetPath().c_str());
492 AddAlias(
"rbreak", cmd_obj_sp,
"--func-regex %1");
499 AddAlias(
"vo", cmd_obj_sp,
"--object-description");
530#define REGISTER_COMMAND_OBJECT(NAME, CLASS) \
531 m_command_dict[NAME] = std::make_shared<CLASS>(*this);
567 const char *break_regexes[][2] = {
568 {
"^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$",
569 "breakpoint set --file '%1' --line %2 --column %3"},
570 {
"^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$",
571 "breakpoint set --file '%1' --line %2"},
572 {
"^/([^/]+)/$",
"breakpoint set --source-pattern-regexp '%1'"},
573 {
"^([[:digit:]]+)[[:space:]]*$",
"breakpoint set --line %1"},
574 {
"^\\*?(0x[[:xdigit:]]+)[[:space:]]*$",
"breakpoint set --address %1"},
575 {
"^[\"']?([-+]?\\[.*\\])[\"']?[[:space:]]*$",
576 "breakpoint set --name '%1'"},
577 {
"^(-.*)$",
"breakpoint set %1"},
578 {
"^(.*[^[:space:]])`(.*[^[:space:]])[[:space:]]*$",
579 "breakpoint set --name '%2' --shlib '%1'"},
580 {
"^\\&(.*[^[:space:]])[[:space:]]*$",
581 "breakpoint set --name '%1' --skip-prologue=0"},
582 {
"^[\"']?(.*[^[:space:]\"'])[\"']?[[:space:]]*$",
583 "breakpoint set --name '%1'"}};
586 size_t num_regexes = std::size(break_regexes);
588 std::unique_ptr<CommandObjectRegexCommand> break_regex_cmd_up(
590 *
this,
"_regexp-break",
591 "Set a breakpoint using one of several shorthand formats.",
593 "_regexp-break <filename>:<linenum>:<colnum>\n"
594 " main.c:12:21 // Break at line 12 and column "
596 "_regexp-break <filename>:<linenum>\n"
597 " main.c:12 // Break at line 12 of "
599 "_regexp-break <linenum>\n"
600 " 12 // Break at line 12 of current "
602 "_regexp-break 0x<address>\n"
603 " 0x1234000 // Break at address "
605 "_regexp-break <name>\n"
606 " main // Break in 'main' after the "
608 "_regexp-break &<name>\n"
609 " &main // Break at first instruction "
611 "_regexp-break <module>`<name>\n"
612 " libc.so`malloc // Break in 'malloc' from "
614 "_regexp-break /<source-regex>/\n"
615 " /break here/ // Break on source lines in "
617 " // containing text 'break "
623 if (break_regex_cmd_up) {
625 for (
size_t i = 0; i < num_regexes; i++) {
626 success = break_regex_cmd_up->AddRegexCommand(break_regexes[i][0],
627 break_regexes[i][1]);
632 break_regex_cmd_up->AddRegexCommand(
"^$",
"breakpoint list --full");
635 CommandObjectSP break_regex_cmd_sp(break_regex_cmd_up.release());
636 m_command_dict[std::string(break_regex_cmd_sp->GetCommandName())] =
641 std::unique_ptr<CommandObjectRegexCommand> tbreak_regex_cmd_up(
643 *
this,
"_regexp-tbreak",
644 "Set a one-shot breakpoint using one of several shorthand formats.",
646 "_regexp-break <filename>:<linenum>:<colnum>\n"
647 " main.c:12:21 // Break at line 12 and column "
649 "_regexp-break <filename>:<linenum>\n"
650 " main.c:12 // Break at line 12 of "
652 "_regexp-break <linenum>\n"
653 " 12 // Break at line 12 of current "
655 "_regexp-break 0x<address>\n"
656 " 0x1234000 // Break at address "
658 "_regexp-break <name>\n"
659 " main // Break in 'main' after the "
661 "_regexp-break &<name>\n"
662 " &main // Break at first instruction "
664 "_regexp-break <module>`<name>\n"
665 " libc.so`malloc // Break in 'malloc' from "
667 "_regexp-break /<source-regex>/\n"
668 " /break here/ // Break on source lines in "
670 " // containing text 'break "
676 if (tbreak_regex_cmd_up) {
678 for (
size_t i = 0; i < num_regexes; i++) {
679 std::string command = break_regexes[i][1];
682 tbreak_regex_cmd_up->AddRegexCommand(break_regexes[i][0], command);
687 tbreak_regex_cmd_up->AddRegexCommand(
"^$",
"breakpoint list --full");
690 CommandObjectSP tbreak_regex_cmd_sp(tbreak_regex_cmd_up.release());
691 m_command_dict[std::string(tbreak_regex_cmd_sp->GetCommandName())] =
696 std::unique_ptr<CommandObjectRegexCommand> attach_regex_cmd_up(
698 *
this,
"_regexp-attach",
"Attach to process by ID or name.",
699 "_regexp-attach <pid> | <process-name>", 0,
false));
700 if (attach_regex_cmd_up) {
701 if (attach_regex_cmd_up->AddRegexCommand(
"^([0-9]+)[[:space:]]*$",
702 "process attach --pid %1") &&
703 attach_regex_cmd_up->AddRegexCommand(
704 "^(-.*|.* -.*)$",
"process attach %1") &&
707 attach_regex_cmd_up->AddRegexCommand(
"^(.+)$",
708 "process attach --name '%1'") &&
709 attach_regex_cmd_up->AddRegexCommand(
"^$",
"process attach")) {
710 CommandObjectSP attach_regex_cmd_sp(attach_regex_cmd_up.release());
711 m_command_dict[std::string(attach_regex_cmd_sp->GetCommandName())] =
716 std::unique_ptr<CommandObjectRegexCommand> down_regex_cmd_up(
718 "Select a newer stack frame. Defaults to "
719 "moving one frame, a numeric argument can "
720 "specify an arbitrary number.",
721 "_regexp-down [<count>]", 0,
false));
722 if (down_regex_cmd_up) {
723 if (down_regex_cmd_up->AddRegexCommand(
"^$",
"frame select -r -1") &&
724 down_regex_cmd_up->AddRegexCommand(
"^([0-9]+)$",
725 "frame select -r -%1")) {
726 CommandObjectSP down_regex_cmd_sp(down_regex_cmd_up.release());
727 m_command_dict[std::string(down_regex_cmd_sp->GetCommandName())] =
732 std::unique_ptr<CommandObjectRegexCommand> up_regex_cmd_up(
735 "Select an older stack frame. Defaults to moving one "
736 "frame, a numeric argument can specify an arbitrary number.",
737 "_regexp-up [<count>]", 0,
false));
738 if (up_regex_cmd_up) {
739 if (up_regex_cmd_up->AddRegexCommand(
"^$",
"frame select -r 1") &&
740 up_regex_cmd_up->AddRegexCommand(
"^([0-9]+)$",
"frame select -r %1")) {
741 CommandObjectSP up_regex_cmd_sp(up_regex_cmd_up.release());
747 std::unique_ptr<CommandObjectRegexCommand> display_regex_cmd_up(
749 *
this,
"_regexp-display",
750 "Evaluate an expression at every stop (see 'help target stop-hook'.)",
751 "_regexp-display expression", 0,
false));
752 if (display_regex_cmd_up) {
753 if (display_regex_cmd_up->AddRegexCommand(
754 "^(.+)$",
"target stop-hook add -o \"expr -- %1\"")) {
755 CommandObjectSP display_regex_cmd_sp(display_regex_cmd_up.release());
756 m_command_dict[std::string(display_regex_cmd_sp->GetCommandName())] =
757 display_regex_cmd_sp;
761 std::unique_ptr<CommandObjectRegexCommand> undisplay_regex_cmd_up(
763 "Stop displaying expression at every "
764 "stop (specified by stop-hook index.)",
765 "_regexp-undisplay stop-hook-number", 0,
767 if (undisplay_regex_cmd_up) {
768 if (undisplay_regex_cmd_up->AddRegexCommand(
"^([0-9]+)$",
769 "target stop-hook delete %1")) {
770 CommandObjectSP undisplay_regex_cmd_sp(undisplay_regex_cmd_up.release());
771 m_command_dict[std::string(undisplay_regex_cmd_sp->GetCommandName())] =
772 undisplay_regex_cmd_sp;
776 std::unique_ptr<CommandObjectRegexCommand> connect_gdb_remote_cmd_up(
779 "Connect to a process via remote GDB server.\n"
780 "If no host is specifed, localhost is assumed.\n"
781 "gdb-remote is an abbreviation for 'process connect --plugin "
782 "gdb-remote connect://<hostname>:<port>'\n",
783 "gdb-remote [<hostname>:]<portnum>", 0,
false));
784 if (connect_gdb_remote_cmd_up) {
785 if (connect_gdb_remote_cmd_up->AddRegexCommand(
786 "^([^:]+|\\[[0-9a-fA-F:]+.*\\]):([0-9]+)$",
787 "process connect --plugin gdb-remote connect://%1:%2") &&
788 connect_gdb_remote_cmd_up->AddRegexCommand(
790 "process connect --plugin gdb-remote connect://localhost:%1")) {
791 CommandObjectSP command_sp(connect_gdb_remote_cmd_up.release());
792 m_command_dict[std::string(command_sp->GetCommandName())] = command_sp;
796 std::unique_ptr<CommandObjectRegexCommand> connect_kdp_remote_cmd_up(
799 "Connect to a process via remote KDP server.\n"
800 "If no UDP port is specified, port 41139 is assumed.\n"
801 "kdp-remote is an abbreviation for 'process connect --plugin "
802 "kdp-remote udp://<hostname>:<port>'\n",
803 "kdp-remote <hostname>[:<portnum>]", 0,
false));
804 if (connect_kdp_remote_cmd_up) {
805 if (connect_kdp_remote_cmd_up->AddRegexCommand(
806 "^([^:]+:[[:digit:]]+)$",
807 "process connect --plugin kdp-remote udp://%1") &&
808 connect_kdp_remote_cmd_up->AddRegexCommand(
809 "^(.+)$",
"process connect --plugin kdp-remote udp://%1:41139")) {
810 CommandObjectSP command_sp(connect_kdp_remote_cmd_up.release());
811 m_command_dict[std::string(command_sp->GetCommandName())] = command_sp;
815 std::unique_ptr<CommandObjectRegexCommand> bt_regex_cmd_up(
818 "Show the current thread's call stack. Any numeric argument "
819 "displays at most that many "
820 "frames. The argument 'all' displays all threads. Use 'settings"
821 " set frame-format' to customize the printing of individual frames "
822 "and 'settings set thread-format' to customize the thread header.",
823 "bt [<digit> | all]", 0,
false));
824 if (bt_regex_cmd_up) {
829 if (bt_regex_cmd_up->AddRegexCommand(
"^([[:digit:]]+)[[:space:]]*$",
830 "thread backtrace -c %1") &&
831 bt_regex_cmd_up->AddRegexCommand(
"^-c ([[:digit:]]+)[[:space:]]*$",
832 "thread backtrace -c %1") &&
833 bt_regex_cmd_up->AddRegexCommand(
"^all[[:space:]]*$",
"thread backtrace all") &&
834 bt_regex_cmd_up->AddRegexCommand(
"^[[:space:]]*$",
"thread backtrace")) {
835 CommandObjectSP command_sp(bt_regex_cmd_up.release());
836 m_command_dict[std::string(command_sp->GetCommandName())] = command_sp;
840 std::unique_ptr<CommandObjectRegexCommand> list_regex_cmd_up(
842 *
this,
"_regexp-list",
843 "List relevant source code using one of several shorthand formats.",
845 "_regexp-list <file>:<line> // List around specific file/line\n"
846 "_regexp-list <line> // List current file around specified "
848 "_regexp-list <function-name> // List specified function\n"
849 "_regexp-list 0x<address> // List around specified address\n"
850 "_regexp-list -[<count>] // List previous <count> lines\n"
851 "_regexp-list // List subsequent lines",
853 if (list_regex_cmd_up) {
854 if (list_regex_cmd_up->AddRegexCommand(
"^([0-9]+)[[:space:]]*$",
855 "source list --line %1") &&
856 list_regex_cmd_up->AddRegexCommand(
857 "^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]"
859 "source list --file '%1' --line %2") &&
860 list_regex_cmd_up->AddRegexCommand(
861 "^\\*?(0x[[:xdigit:]]+)[[:space:]]*$",
862 "source list --address %1") &&
863 list_regex_cmd_up->AddRegexCommand(
"^-[[:space:]]*$",
864 "source list --reverse") &&
865 list_regex_cmd_up->AddRegexCommand(
866 "^-([[:digit:]]+)[[:space:]]*$",
867 "source list --reverse --count %1") &&
868 list_regex_cmd_up->AddRegexCommand(
"^(.+)$",
869 "source list --name \"%1\"") &&
870 list_regex_cmd_up->AddRegexCommand(
"^$",
"source list")) {
871 CommandObjectSP list_regex_cmd_sp(list_regex_cmd_up.release());
872 m_command_dict[std::string(list_regex_cmd_sp->GetCommandName())] =
877 std::unique_ptr<CommandObjectRegexCommand> env_regex_cmd_up(
879 *
this,
"_regexp-env",
880 "Shorthand for viewing and setting environment variables.",
882 "_regexp-env // Show environment\n"
883 "_regexp-env <name>=<value> // Set an environment variable",
885 if (env_regex_cmd_up) {
886 if (env_regex_cmd_up->AddRegexCommand(
"^$",
887 "settings show target.env-vars") &&
888 env_regex_cmd_up->AddRegexCommand(
"^([A-Za-z_][A-Za-z_0-9]*=.*)$",
889 "settings set target.env-vars %1")) {
890 CommandObjectSP env_regex_cmd_sp(env_regex_cmd_up.release());
896 std::unique_ptr<CommandObjectRegexCommand> jump_regex_cmd_up(
898 *
this,
"_regexp-jump",
"Set the program counter to a new address.",
900 "_regexp-jump <line>\n"
901 "_regexp-jump +<line-offset> | -<line-offset>\n"
902 "_regexp-jump <file>:<line>\n"
903 "_regexp-jump *<addr>\n",
905 if (jump_regex_cmd_up) {
906 if (jump_regex_cmd_up->AddRegexCommand(
"^\\*(.*)$",
907 "thread jump --addr %1") &&
908 jump_regex_cmd_up->AddRegexCommand(
"^([0-9]+)$",
909 "thread jump --line %1") &&
910 jump_regex_cmd_up->AddRegexCommand(
"^([^:]+):([0-9]+)$",
911 "thread jump --file %1 --line %2") &&
912 jump_regex_cmd_up->AddRegexCommand(
"^([+\\-][0-9]+)$",
913 "thread jump --by %1")) {
914 CommandObjectSP jump_regex_cmd_sp(jump_regex_cmd_up.release());
915 m_command_dict[std::string(jump_regex_cmd_sp->GetCommandName())] =
922 const char *cmd_str,
bool include_aliases,
StringList &matches,
927 if (include_aliases) {
936 Args &path,
bool leaf_is_command,
Status &result) {
939 auto get_multi_or_report_error =
940 [&result](CommandObjectSP cmd_sp,
946 if (!cmd_sp->IsUserCommand()) {
968 if (num_args == 1 && leaf_is_command) {
978 get_multi_or_report_error(cur_cmd_sp, cur_name);
979 if (cur_as_multi ==
nullptr)
982 size_t num_path_elements = num_args - (leaf_is_command ? 1 : 0);
983 for (
size_t cursor = 1; cursor < num_path_elements && cur_as_multi !=
nullptr;
987 cur_as_multi = get_multi_or_report_error(cur_cmd_sp, cur_name);
996 CommandObjectSP command_sp;
998 std::string cmd = std::string(cmd_str);
1003 command_sp = pos->second;
1009 command_sp = alias_pos->second;
1015 command_sp = pos->second;
1021 command_sp = pos->second;
1024 if (!exact && !command_sp) {
1027 CommandObjectSP user_match_sp, user_mw_match_sp, alias_match_sp,
1031 if (matches ==
nullptr)
1032 matches = &local_matches;
1034 unsigned int num_cmd_matches = 0;
1035 unsigned int num_alias_matches = 0;
1036 unsigned int num_user_matches = 0;
1037 unsigned int num_user_mw_matches = 0;
1045 *matches, descriptions);
1048 if (num_cmd_matches == 1) {
1052 real_match_sp = pos->second;
1057 *matches, descriptions);
1060 if (num_alias_matches == 1) {
1064 alias_match_sp = alias_pos->second;
1069 *matches, descriptions);
1072 if (num_user_matches == 1) {
1078 user_match_sp = pos->second;
1086 if (num_user_mw_matches == 1) {
1092 user_mw_match_sp = pos->second;
1098 if (num_user_matches + num_user_mw_matches + num_cmd_matches +
1099 num_alias_matches ==
1101 if (num_cmd_matches)
1102 return real_match_sp;
1103 else if (num_alias_matches)
1104 return alias_match_sp;
1105 else if (num_user_mw_matches)
1106 return user_mw_match_sp;
1108 return user_match_sp;
1110 }
else if (matches && command_sp) {
1120 const lldb::CommandObjectSP &cmd_sp,
1123 lldbassert((
this == &cmd_sp->GetCommandInterpreter()) &&
1124 "tried to add a CommandObject from a different interpreter");
1129 cmd_sp->SetIsUserCommand(
false);
1131 std::string name_sstr(name);
1134 if (!can_replace || !name_iter->second->IsRemovable())
1136 name_iter->second = cmd_sp;
1144 const lldb::CommandObjectSP &cmd_sp,
1148 lldbassert((
this == &cmd_sp->GetCommandInterpreter()) &&
1149 "tried to add a CommandObject from a different interpreter");
1151 result.
SetErrorString(
"can't use the empty string for a command name");
1162 result.
SetErrorString(
"user command exists and force replace not set");
1165 if (cmd_sp->IsMultiwordObject()) {
1168 "can't replace explicitly non-removable multi-word command");
1172 if (!
m_user_dict[std::string(name)]->IsRemovable()) {
1173 result.
SetErrorString(
"can't replace explicitly non-removable command");
1179 cmd_sp->SetIsUserCommand(
true);
1181 if (cmd_sp->IsMultiwordObject())
1190 bool include_aliases)
const {
1192 Args cmd_words(cmd_str);
1194 if (cmd_str.empty())
1202 CommandObjectSP cmd_obj_sp =
1211 for (
size_t i = 1; i < end; ++i) {
1212 if (!cmd_obj_sp->IsMultiwordObject()) {
1235 GetCommandSP(cmd_str,
false,
true, matches, descriptions).get();
1243 command_obj =
GetCommandSP(cmd_str,
true,
true, matches, descriptions).get();
1250 command_obj =
GetCommandSP(cmd_str,
false,
false,
nullptr).get();
1263 return GetCommandSP(cmd_str,
true,
false, matches, descriptions).get();
1268 std::string cmd_str(cmd);
1270 auto found_elem = map.find(std::string(cmd));
1271 if (found_elem == map.end())
1294 StringList *matches_ptr = matches ? matches : &tmp_list;
1297 cmd_str, *matches_ptr);
1307 std::string &full_name)
const {
1311 full_name.assign(std::string(cmd));
1315 size_t num_alias_matches;
1318 if (num_alias_matches == 1) {
1321 const bool include_aliases =
false;
1322 const bool exact =
false;
1323 CommandObjectSP cmd_obj_sp(
1324 GetCommandSP(cmd, include_aliases, exact, ®ular_matches));
1325 if (cmd_obj_sp || regular_matches.
GetSize() > 0)
1350 lldb::CommandObjectSP &command_obj_sp,
1351 llvm::StringRef args_string) {
1352 if (command_obj_sp.get())
1353 lldbassert((
this == &command_obj_sp->GetCommandInterpreter()) &&
1354 "tried to add a CommandObject from a different interpreter");
1356 std::unique_ptr<CommandAlias> command_alias_up(
1357 new CommandAlias(*
this, command_obj_sp, args_string, alias_name));
1359 if (command_alias_up && command_alias_up->IsValid()) {
1361 CommandObjectSP(command_alias_up.get());
1362 return command_alias_up.release();
1380 if (force || pos->second->IsRemovable()) {
1391 CommandObject::CommandMap::iterator pos =
1401 CommandObject::CommandMap::iterator pos =
1412 llvm::StringRef help_prologue(
GetDebugger().GetIOHandlerHelpPrologue());
1413 if (!help_prologue.empty()) {
1418 CommandObject::CommandMap::const_iterator pos;
1427 (pos->first.compare(0, 1,
"_") == 0))
1431 pos->second->GetHelp(), max_len);
1439 "Current command abbreviations "
1440 "(type '%shelp command alias' for more info):\n",
1448 alias_pos->second->GetHelp(), max_len);
1460 pos->second->GetHelp(), max_len);
1467 result.
AppendMessage(
"Current user-defined container commands:");
1472 pos->second->GetHelp(), max_len);
1478 "For more information on any command, type '%shelp <command-name>'.\n",
1483 llvm::StringRef &command_string) {
1489 size_t start = command_string.find_first_not_of(
k_white_space);
1493 if (start != std::string::npos) {
1496 if (end == std::string::npos)
1497 end = command_string.size();
1498 std::string cmd_word =
1499 std::string(command_string.substr(start, end - start));
1501 if (cmd_obj ==
nullptr)
1511 cmd_obj = sub_cmd_obj;
1523 end >= command_string.size())
1526 start = command_string.find_first_not_of(
k_white_space, end);
1532 command_string = command_string.substr(end);
1537 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
1541 if (pos == std::string::npos)
1550 const size_t s_len = s.size();
1552 while (offset < s_len) {
1553 size_t pos = s.find(
"--", offset);
1554 if (pos == std::string::npos)
1557 if (llvm::isSpace(s[pos - 1])) {
1560 if ((pos + 2 >= s_len) || llvm::isSpace(s[pos + 2])) {
1567 return std::string::npos;
1571 std::string &suffix,
char "e_char) {
1576 bool result =
false;
1579 if (!command_string.empty()) {
1580 const char first_char = command_string[0];
1581 if (first_char ==
'\'' || first_char ==
'"') {
1582 quote_char = first_char;
1583 const size_t end_quote_pos = command_string.find(quote_char, 1);
1584 if (end_quote_pos == std::string::npos) {
1585 command.swap(command_string);
1586 command_string.erase();
1588 command.assign(command_string, 1, end_quote_pos - 1);
1589 if (end_quote_pos + 1 < command_string.size())
1590 command_string.erase(0, command_string.find_first_not_of(
1593 command_string.erase();
1596 const size_t first_space_pos =
1598 if (first_space_pos == std::string::npos) {
1599 command.swap(command_string);
1600 command_string.erase();
1602 command.assign(command_string, 0, first_space_pos);
1603 command_string.erase(0, command_string.find_first_not_of(
1610 if (!command.empty()) {
1612 if (command[0] !=
'-' && command[0] !=
'_') {
1614 if (pos > 0 && pos != std::string::npos) {
1615 suffix.assign(command.begin() + pos, command.end());
1625 llvm::StringRef alias_name, std::string &raw_input_string,
1628 Args cmd_args(raw_input_string);
1632 if (!alias_cmd_obj || !alias_cmd_obj->
IsAlias()) {
1633 alias_result.clear();
1634 return alias_cmd_obj;
1636 std::pair<CommandObjectSP, OptionArgVectorSP> desugared =
1639 alias_cmd_obj = desugared.first.get();
1640 std::string alias_name_str = std::string(alias_name);
1643 cmd_args.
Unshift(alias_name_str);
1647 if (!option_arg_vector_sp.get()) {
1648 alias_result = std::string(result_str.
GetString());
1649 return alias_cmd_obj;
1656 for (
const auto &entry : *option_arg_vector) {
1657 std::tie(option, value_type, value) = entry;
1659 result_str.
Printf(
" %s", value.c_str());
1663 result_str.
Printf(
" %s", option.c_str());
1671 result_str.
Printf(
"%s", value.c_str());
1675 "need at least %d arguments to use "
1681 size_t strpos = raw_input_string.find(entry.
c_str());
1683 if (strpos != std::string::npos) {
1684 const size_t start_fudge = quote_char ==
'\0' ? 0 : 1;
1685 const size_t len_fudge = quote_char ==
'\0' ? 0 : 2;
1688 if (strpos < start_fudge) {
1689 result.
AppendError(
"Unmatched quote at command beginning.");
1692 llvm::StringRef arg_text = entry.
ref();
1693 if (strpos - start_fudge + arg_text.size() + len_fudge >
1694 raw_input_string.size()) {
1695 result.
AppendError(
"Unmatched quote at command end.");
1698 raw_input_string = raw_input_string.erase(
1699 strpos - start_fudge,
1702 if (quote_char ==
'\0')
1705 result_str.
Printf(
"%c%s%c", quote_char, entry.
c_str(), quote_char);
1709 alias_result = std::string(result_str.
GetString());
1710 return alias_cmd_obj;
1721 size_t start_backtick;
1723 while ((start_backtick = command.find(
'`', pos)) != std::string::npos) {
1728 if (start_backtick > 0 && command[start_backtick - 1] ==
'\\') {
1731 command.erase(start_backtick - 1, 1);
1733 pos = start_backtick;
1737 const size_t expr_content_start = start_backtick + 1;
1738 const size_t end_backtick = command.find(
'`', expr_content_start);
1740 if (end_backtick == std::string::npos) {
1745 if (end_backtick == expr_content_start) {
1747 command.erase(start_backtick, 2);
1751 std::string expr_str(command, expr_content_start,
1752 end_backtick - expr_content_start);
1758 command.erase(start_backtick, end_backtick - start_backtick + 1);
1759 command.insert(start_backtick, std::string(expr_str));
1760 pos = start_backtick + expr_str.size();
1776 ValueObjectSP expr_result_valobj_sp;
1788 expr_result_valobj_sp, options);
1792 if (expr_result_valobj_sp)
1793 expr_result_valobj_sp =
1794 expr_result_valobj_sp->GetQualifiedRepresentationIfAvailable(
1795 expr_result_valobj_sp->GetDynamicValueType(),
true);
1796 if (expr_result_valobj_sp->ResolveValue(scalar)) {
1799 const bool show_type =
false;
1800 scalar.
GetValue(&value_strm, show_type);
1801 size_t value_string_size = value_strm.
GetSize();
1802 if (value_string_size) {
1803 expr_str = value_strm.
GetData();
1805 error.SetErrorStringWithFormat(
"expression value didn't result "
1806 "in a scalar value for the "
1811 error.SetErrorStringWithFormat(
"expression value didn't result "
1812 "in a scalar value for the "
1823 if (expr_result_valobj_sp)
1824 error = expr_result_valobj_sp->GetError();
1826 if (
error.Success()) {
1827 switch (expr_result) {
1829 error.SetErrorStringWithFormat(
1830 "expression setup error for the expression '%s'", expr_str.c_str());
1833 error.SetErrorStringWithFormat(
1834 "expression parse error for the expression '%s'", expr_str.c_str());
1837 error.SetErrorStringWithFormat(
1838 "expression error fetching result for the expression '%s'",
1844 error.SetErrorStringWithFormat(
1845 "expression discarded for the expression '%s'", expr_str.c_str());
1848 error.SetErrorStringWithFormat(
1849 "expression interrupted for the expression '%s'", expr_str.c_str());
1852 error.SetErrorStringWithFormat(
1853 "expression hit breakpoint for the expression '%s'",
1857 error.SetErrorStringWithFormat(
1858 "expression timed out for the expression '%s'", expr_str.c_str());
1861 error.SetErrorStringWithFormat(
"expression stop at entry point "
1862 "for debugging for the "
1867 error.SetErrorStringWithFormat(
1868 "expression thread vanished for the expression '%s'",
1882 bool status =
HandleCommand(command_line, lazy_add_to_history, result);
1890 bool force_repeat_command) {
1891 std::string command_string(command_line);
1892 std::string original_command_string(command_line);
1895 llvm::PrettyStackTraceFormat stack_trace(
"HandleCommand(command = \"%s\")",
1898 LLDB_LOGF(log,
"Processing command: %s", command_line);
1906 bool add_to_history;
1910 add_to_history = (lazy_add_to_history ==
eLazyBoolYes);
1914 bool empty_command =
false;
1915 bool comment_command =
false;
1916 if (command_string.empty())
1917 empty_command =
true;
1919 const char *k_space_characters =
"\t\n\v\f\r ";
1921 size_t non_space = command_string.find_first_not_of(k_space_characters);
1924 if (non_space == std::string::npos)
1925 empty_command =
true;
1927 comment_command =
true;
1929 llvm::StringRef search_str(command_string);
1930 search_str = search_str.drop_front(non_space);
1932 add_to_history =
false;
1933 command_string = std::string(*hist_str);
1934 original_command_string = std::string(*hist_str);
1937 command_string.c_str());
1943 if (empty_command) {
1955 command_string = command_line;
1956 original_command_string = command_line;
1962 add_to_history =
false;
1963 }
else if (comment_command) {
2003 llvm::StringRef command_name = cmd_obj ? cmd_obj->
GetCommandName() :
"<not found>";
2004 LLDB_LOGF(log,
"HandleCommand, cmd_obj : '%s'", command_name.str().c_str());
2005 LLDB_LOGF(log,
"HandleCommand, (revised) command_string: '%s'",
2006 command_string.c_str());
2007 const bool wants_raw_input =
2009 LLDB_LOGF(log,
"HandleCommand, wants_raw_input:'%s'",
2010 wants_raw_input ?
"True" :
"False");
2018 if (cmd_obj !=
nullptr) {
2019 bool generate_repeat_command = add_to_history;
2023 generate_repeat_command |= empty_command;
2028 generate_repeat_command |= force_repeat_command;
2029 if (generate_repeat_command) {
2030 Args command_args(command_string);
2031 std::optional<std::string> repeat_command =
2033 if (repeat_command) {
2034 LLDB_LOGF(log,
"Repeat command: %s", repeat_command->data());
2044 std::string remainder;
2045 const std::size_t actual_cmd_name_len = cmd_obj->
GetCommandName().size();
2046 if (actual_cmd_name_len < command_string.length())
2047 remainder = command_string.substr(actual_cmd_name_len);
2051 if (pos != 0 && pos != std::string::npos)
2052 remainder.erase(0, pos);
2055 log,
"HandleCommand, command line after removing command name(s): '%s'",
2058 cmd_obj->
Execute(remainder.c_str(), result);
2061 LLDB_LOGF(log,
"HandleCommand, command %s",
2062 (result.
Succeeded() ?
"succeeded" :
"did not succeed"));
2071 bool look_for_subcommand =
false;
2077 bool include_aliases =
true;
2088 &new_matches, &new_descriptions);
2095 look_for_subcommand =
true;
2110 if (command_object) {
2123 if (!first_arg.empty()) {
2128 request.
AddCompletion(*hist_str,
"Previous command history event",
2137std::optional<std::string>
2140 return std::nullopt;
2142 for (
int i = s - 1; i >= 0; --i) {
2144 if (entry.consume_front(line))
2147 return std::nullopt;
2151 EventSP prompt_change_event_sp(
2162 return default_answer;
2166 IOHandlerSP io_handler_sp(confirm);
2195 const char *alias_name,
2197 std::string &raw_input_string,
2205 std::string alias_name_str = alias_name;
2207 cmd_args.
Unshift(alias_name_str);
2213 if (option_arg_vector_sp.get()) {
2214 if (wants_raw_input) {
2218 size_t pos = raw_input_string.find(
" -- ");
2219 if (pos == std::string::npos) {
2221 raw_input_string.insert(0,
" -- ");
2227 std::vector<bool> used(old_size + 1,
false);
2234 for (
const auto &option_entry : *option_arg_vector) {
2235 std::tie(option, value_type, value) = option_entry;
2237 if (!wants_raw_input || (value !=
"--")) {
2261 "need at least %d arguments to use "
2269 if (strpos != std::string::npos) {
2270 raw_input_string = raw_input_string.erase(
2283 for (
auto entry : llvm::enumerate(cmd_args.
entries())) {
2284 if (!used[entry.index()] && !wants_raw_input)
2297 if (wants_raw_input) {
2313 const char *cptr = in_string;
2316 if (cptr[0] ==
'%') {
2320 if (isdigit(cptr[0])) {
2321 const char *start = cptr;
2322 while (isdigit(cptr[0]))
2327 if (cptr[0] ==
'\0')
2328 position = atoi(start);
2336 llvm::StringRef suffix = {}) {
2337 std::string init_file_name =
".lldbinit";
2338 if (!suffix.empty()) {
2339 init_file_name.append(
"-");
2340 init_file_name.append(suffix.str());
2344 llvm::sys::path::append(init_file, init_file_name);
2354 language = *main_repl_language;
2359 std::string init_file_name =
2360 (llvm::Twine(
".lldbinit-") +
2362 llvm::Twine(
"-repl"))
2365 llvm::sys::path::append(init_file, init_file_name);
2370 llvm::StringRef s =
".lldbinit";
2371 init_file.assign(s.begin(), s.end());
2403 llvm::SmallString<128> init_file;
2413 switch (should_load) {
2421 llvm::SmallString<128> home_init_file;
2423 if (llvm::sys::path::parent_path(init_file) ==
2424 llvm::sys::path::parent_path(home_init_file)) {
2444 llvm::SmallString<128> init_file;
2449 if (init_file.empty())
2453 llvm::StringRef program_name =
2454 HostInfo::GetProgramFileSpec().GetFilename().GetStringRef();
2455 llvm::SmallString<128> program_init_file;
2458 init_file = program_init_file;
2465#ifdef LLDB_GLOBAL_INIT_DIRECTORY
2467 FileSpec init_file(LLDB_GLOBAL_INIT_DIRECTORY);
2481 return prefix ==
nullptr ?
"" : prefix;
2485 PlatformSP platform_sp;
2486 if (prefer_target_platform) {
2500 TargetSP target_sp = exe_ctx.GetTargetSP();
2504 ProcessSP process_sp(target_sp->GetProcessSP());
2511 for (
const auto &thread_sp : process_sp->GetThreadList().Threads()) {
2512 StopInfoSP stop_info = thread_sp->GetStopInfo();
2520 const StopReason reason = stop_info->GetStopReason();
2527 const auto stop_signal =
static_cast<int32_t
>(stop_info->GetValue());
2528 UnixSignalsSP signals_sp = process_sp->GetUnixSignals();
2529 if (!signals_sp || !signals_sp->SignalIsValid(stop_signal))
2533 const auto sigint_num = signals_sp->GetSignalNumberFromName(
"SIGINT");
2534 const auto sigstop_num = signals_sp->GetSignalNumberFromName(
"SIGSTOP");
2535 if ((stop_signal != sigint_num) && (stop_signal != sigstop_num))
2558 size_t num_lines = commands.
GetSize();
2570 for (
size_t idx = 0; idx < num_lines; idx++) {
2599 if (!success || !tmp_result.
Succeeded()) {
2601 if (error_msg.empty())
2602 error_msg =
"<unknown error>.\n";
2605 "Aborting reading of commands after command #%" PRIu64
2606 ": '%s' failed with %s",
2607 (uint64_t)idx, cmd, error_msg.str().c_str());
2612 "Command #%" PRIu64
" '%s' failed with %s", (uint64_t)idx + 1, cmd,
2613 error_msg.str().c_str());
2634 if (idx != num_lines - 1)
2636 "Aborting reading of commands after command #%" PRIu64
2637 ": '%s' continued the target.\n",
2638 (uint64_t)idx + 1, cmd);
2641 " '%s' continued the target.\n",
2642 (uint64_t)idx + 1, cmd);
2654 if (idx != num_lines - 1)
2656 "Aborting reading of commands after command #%" PRIu64
2657 ": '%s' stopped with a signal or exception.\n",
2658 (uint64_t)idx + 1, cmd);
2661 "Command #%" PRIu64
" '%s' stopped with a signal or exception.\n",
2662 (uint64_t)idx + 1, cmd);
2699 "Error reading commands from file %s - file not found.\n",
2704 std::string cmd_file_path = cmd_file.
GetPath();
2705 auto input_file_up =
2707 if (!input_file_up) {
2708 std::string
error = llvm::toString(input_file_up.takeError());
2710 "error: an error occurred read file '{0}': {1}\n", cmd_file_path,
2711 llvm::fmt_consume(input_file_up.takeError()));
2714 FileSP input_file_sp = FileSP(std::move(input_file_up.get()));
2801 cmd_file_path.c_str());
2806 lldb::StreamFileSP empty_stream_sp;
2817 debugger.
GetPrompt(), llvm::StringRef(),
2847 llvm::StringRef prefix,
2848 llvm::StringRef help_text) {
2851 size_t line_width_max = max_columns - prefix.size();
2852 if (line_width_max < 16)
2853 line_width_max = help_text.size() + prefix.size();
2856 bool prefixed_yet =
false;
2858 if (help_text.empty())
2859 help_text =
"No help text";
2860 while (!help_text.empty()) {
2862 if (!prefixed_yet) {
2864 prefixed_yet =
true;
2869 llvm::StringRef this_line = help_text.substr(0, line_width_max);
2872 std::size_t first_newline = this_line.find_first_of(
"\n");
2875 std::size_t last_space = llvm::StringRef::npos;
2876 if (this_line.size() != help_text.size())
2877 last_space = this_line.find_last_of(
" \t");
2880 this_line = this_line.substr(0, std::min(first_newline, last_space));
2885 help_text = help_text.drop_front(this_line.size()).ltrim();
2891 llvm::StringRef word_text,
2892 llvm::StringRef separator,
2893 llvm::StringRef help_text,
2894 size_t max_word_len) {
2896 prefix_stream.
Printf(
" %-*s %*s ", (
int)max_word_len, word_text.data(),
2897 (
int)separator.size(), separator.data());
2902 llvm::StringRef separator,
2903 llvm::StringRef help_text,
2905 int indent_size = max_word_len + separator.size() + 2;
2910 text_strm.
Printf(
"%-*s ", (
int)max_word_len, word_text.data());
2911 text_strm << separator <<
" " << help_text;
2915 llvm::StringRef text = text_strm.
GetString();
2919 auto nextWordLength = [](llvm::StringRef S) {
2920 size_t pos = S.find(
' ');
2921 return pos == llvm::StringRef::npos ? S.size() : pos;
2924 while (!text.empty()) {
2925 if (text.front() ==
'\n' ||
2926 (text.front() ==
' ' && nextWordLength(text.ltrim(
' ')) > chars_left)) {
2929 chars_left = max_columns - indent_size;
2930 if (text.front() ==
'\n')
2931 text = text.drop_front();
2933 text = text.ltrim(
' ');
2937 text = text.drop_front();
2946 llvm::StringRef search_word,
StringList &commands_found,
2948 for (
const auto &pair : command_map) {
2949 llvm::StringRef command_name = pair.first;
2952 const bool search_short_help =
true;
2953 const bool search_long_help =
false;
2954 const bool search_syntax =
false;
2955 const bool search_options =
false;
2956 if (command_name.contains_insensitive(search_word) ||
2958 search_long_help, search_syntax,
2967 multiword_cmd->GetSubcommandDictionary());
2968 for (
const auto &subcommand_name : subcommands_found) {
2969 std::string qualified_name =
2970 (command_name +
" " + subcommand_name).str();
2980 bool search_builtin_commands,
2981 bool search_user_commands,
2982 bool search_alias_commands,
2983 bool search_user_mw_commands) {
2984 CommandObject::CommandMap::const_iterator pos;
2986 if (search_builtin_commands)
2990 if (search_user_commands)
2994 if (search_user_mw_commands)
2998 if (search_alias_commands)
3053 bool was_interrupted =
3056 return was_interrupted;
3060 llvm::StringRef str,
3066 bool had_output = !str.empty();
3067 while (!str.empty()) {
3068 llvm::StringRef line;
3069 std::tie(line, str) = str.split(
'\n');
3071 std::lock_guard<std::recursive_mutex> guard(io_handler.
GetOutputMutex());
3072 stream->Write(line.data(), line.size());
3073 stream->Write(
"\n", 1);
3077 std::lock_guard<std::recursive_mutex> guard(io_handler.
GetOutputMutex());
3078 if (had_output &&
GetDebugger().InterruptRequested())
3079 stream->Printf(
"\n... Interrupted.\n");
3084 llvm::StringRef line,
const Flags &io_handler_flags)
const {
3088 llvm::StringRef command = line.trim();
3089 if (command.empty())
3099 std::string &line) {
3105 if (!is_interactive) {
3117 std::lock_guard<std::recursive_mutex> guard(io_handler.
GetOutputMutex());
3119 "%s%s\n", io_handler.
GetPrompt(), line.c_str());
3126 bool pushed_exe_ctx =
false;
3129 pushed_exe_ctx =
true;
3131 auto finalize = llvm::make_scope_exit([
this, pushed_exe_ctx]() {
3140 if ((result.Succeeded() &&
3146 if (!result.GetImmediateOutputStream()) {
3147 llvm::StringRef output = result.GetOutputData();
3152 if (!result.GetImmediateErrorStream()) {
3153 llvm::StringRef
error = result.GetErrorData();
3160 switch (result.GetStatus()) {
3189 result.GetDidChangeProcessState() &&
3214 if (script_interpreter) {
3223 if (output_file == std::nullopt || output_file->empty()) {
3224 std::string now = llvm::to_string(std::chrono::system_clock::now());
3225 std::replace(now.begin(), now.end(),
' ',
'_');
3226 const std::string file_name =
"lldb_session_" + now +
".log";
3231 save_location = HostInfo::GetGlobalTempDir();
3235 output_file = save_location.
GetPath();
3238 auto error_out = [&](llvm::StringRef error_message, std::string description) {
3240 output_file, description);
3242 "Failed to save session's transcripts to {0}!", *output_file);
3253 return error_out(
"Unable to create file",
3254 llvm::toString(opened_file.takeError()));
3256 FileUP file = std::move(opened_file.get());
3263 return error_out(
"Unable to write to destination file",
3264 "Bytes written do not match transcript size.");
3268 output_file->c_str());
3272 error = file->GetFileSpec(
const_cast<FileSpec &
>(file_spec));
3273 if (
error.Success()) {
3296 IOHandlerSP io_handler_sp(
3299 llvm::StringRef(prompt),
3306 if (io_handler_sp) {
3307 io_handler_sp->SetUserData(baton);
3315 IOHandlerSP io_handler_sp(
3318 llvm::StringRef(prompt),
3325 if (io_handler_sp) {
3326 io_handler_sp->SetUserData(baton);
3384 bool force_create =
true;
3412 std::string scratch_command(command_line);
3416 bool wants_raw_input =
false;
3417 std::string next_word;
3421 char quote_char =
'\0';
3424 if (cmd_obj ==
nullptr) {
3425 std::string full_name;
3428 bool is_real_command =
3429 (!is_alias) || (cmd_obj !=
nullptr && !cmd_obj->
IsAlias());
3430 if (!is_real_command) {
3432 std::string alias_result;
3435 revised_command_line.
Printf(
"%s", alias_result.c_str());
3442 revised_command_line.
Printf(
"%s", cmd_name.str().c_str());
3445 revised_command_line.
Printf(
"%s", next_word.c_str());
3456 revised_command_line.
Clear();
3457 revised_command_line.
Printf(
"%s", sub_cmd_name.str().c_str());
3458 cmd_obj = sub_cmd_obj;
3462 revised_command_line.
Printf(
" %c%s%s%c", quote_char,
3463 next_word.c_str(), suffix.c_str(),
3466 revised_command_line.
Printf(
" %s%s", next_word.c_str(),
3472 revised_command_line.
Printf(
" %c%s%s%c", quote_char,
3473 next_word.c_str(), suffix.c_str(),
3476 revised_command_line.
Printf(
" %s%s", next_word.c_str(),
3482 if (cmd_obj ==
nullptr) {
3483 const size_t num_matches = matches.
GetSize();
3486 error_msg.
Printf(
"Ambiguous command '%s'. Possible matches:\n",
3489 for (
uint32_t i = 0; i < num_matches; ++i) {
3503 if (!suffix.empty()) {
3505 "command '%s' did not recognize '%s%s%s' as valid (subcommand "
3506 "might be invalid).\n",
3508 next_word.empty() ?
"" : next_word.c_str(),
3509 next_word.empty() ?
" -- " :
" ", suffix.c_str());
3515 if (!suffix.empty()) {
3516 switch (suffix[0]) {
3521 if (command_options &&
3523 std::string gdb_format_option(
"--gdb-format=");
3524 gdb_format_option += (suffix.c_str() + 1);
3526 std::string cmd = std::string(revised_command_line.
GetString());
3528 if (arg_terminator_idx != std::string::npos) {
3531 gdb_format_option.append(1,
' ');
3532 cmd.insert(arg_terminator_idx, gdb_format_option);
3533 revised_command_line.
Clear();
3536 revised_command_line.
Printf(
" %s", gdb_format_option.c_str());
3538 if (wants_raw_input &&
3543 "the '%s' command doesn't support the --gdb-format option\n",
3552 "unknown command shorthand suffix: '%s'\n", suffix.c_str());
3557 if (scratch_command.empty())
3561 if (!scratch_command.empty())
3562 revised_command_line.
Printf(
" %s", scratch_command.c_str());
3564 if (cmd_obj !=
nullptr)
3565 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
Status PreprocessToken(std::string &token)
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.
FileSpec GetCurrentSourceDir()
void SetEchoCommentCommands(bool enable)
bool RemoveCommand(llvm::StringRef cmd, bool force=false)
Remove a command if it is removable (python or regex command).
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()
Manually start the global event handler thread.
void StopEventHandlerThread()
Manually stop the debugger's default event handler.
void SetAsyncExecution(bool async)
HostThread SetIOHandlerThread(HostThread &new_thread)
lldb::FileSP GetInputFileSP()
bool StartIOHandlerThread()
bool IsTopIOHandler(const lldb::IOHandlerSP &reader_sp)
bool IsIOHandlerThreadCurrentThread() const
uint64_t GetTerminalWidth() const
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()
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 GetExternalEditor() const
llvm::StringRef GetPrompt() const
void FlushProcessOutput(Process &process, bool flush_stdout, bool flush_stderr)
Force flushing the process's pending stdout and stderr to the debugger's asynchronous stdout and stde...
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 lldb::thread_t GetCurrentThread()
Get the thread token (the one returned by ThreadCreate when the thread was created) for the calling t...
static bool IsInteractiveGraphicSession()
Check if we're running in an interactive graphical session.
static llvm::Error OpenFileInExternalEditor(llvm::StringRef editor, const FileSpec &file_spec, uint32_t line_no)
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
bool SetPropertyAtIndex(uint32_t idx, T t, const ExecutionContext *exe_ctx=nullptr) const
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.