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");
535#define REGISTER_COMMAND_OBJECT(NAME, CLASS) \
536 m_command_dict[NAME] = std::make_shared<CLASS>(*this);
572 const char *break_regexes[][2] = {
573 {
"^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$",
574 "breakpoint set --file '%1' --line %2 --column %3"},
575 {
"^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$",
576 "breakpoint set --file '%1' --line %2"},
577 {
"^/([^/]+)/$",
"breakpoint set --source-pattern-regexp '%1'"},
578 {
"^([[:digit:]]+)[[:space:]]*$",
"breakpoint set --line %1"},
579 {
"^\\*?(0x[[:xdigit:]]+)[[:space:]]*$",
"breakpoint set --address %1"},
580 {
"^[\"']?([-+]?\\[.*\\])[\"']?[[:space:]]*$",
581 "breakpoint set --name '%1'"},
582 {
"^(-.*)$",
"breakpoint set %1"},
583 {
"^(.*[^[:space:]])`(.*[^[:space:]])[[:space:]]*$",
584 "breakpoint set --name '%2' --shlib '%1'"},
585 {
"^\\&(.*[^[:space:]])[[:space:]]*$",
586 "breakpoint set --name '%1' --skip-prologue=0"},
587 {
"^[\"']?(.*[^[:space:]\"'])[\"']?[[:space:]]*$",
588 "breakpoint set --name '%1'"}};
591 size_t num_regexes = std::size(break_regexes);
593 std::unique_ptr<CommandObjectRegexCommand> break_regex_cmd_up(
595 *
this,
"_regexp-break",
596 "Set a breakpoint using one of several shorthand formats.",
598 "_regexp-break <filename>:<linenum>:<colnum>\n"
599 " main.c:12:21 // Break at line 12 and column "
601 "_regexp-break <filename>:<linenum>\n"
602 " main.c:12 // Break at line 12 of "
604 "_regexp-break <linenum>\n"
605 " 12 // Break at line 12 of current "
607 "_regexp-break 0x<address>\n"
608 " 0x1234000 // Break at address "
610 "_regexp-break <name>\n"
611 " main // Break in 'main' after the "
613 "_regexp-break &<name>\n"
614 " &main // Break at first instruction "
616 "_regexp-break <module>`<name>\n"
617 " libc.so`malloc // Break in 'malloc' from "
619 "_regexp-break /<source-regex>/\n"
620 " /break here/ // Break on source lines in "
622 " // containing text 'break "
626 if (break_regex_cmd_up) {
628 for (
size_t i = 0; i < num_regexes; i++) {
629 success = break_regex_cmd_up->AddRegexCommand(break_regexes[i][0],
630 break_regexes[i][1]);
635 break_regex_cmd_up->AddRegexCommand(
"^$",
"breakpoint list --full");
639 m_command_dict[std::string(break_regex_cmd_sp->GetCommandName())] =
644 std::unique_ptr<CommandObjectRegexCommand> tbreak_regex_cmd_up(
646 *
this,
"_regexp-tbreak",
647 "Set a one-shot breakpoint using one of several shorthand formats.",
649 "_regexp-break <filename>:<linenum>:<colnum>\n"
650 " main.c:12:21 // Break at line 12 and column "
652 "_regexp-break <filename>:<linenum>\n"
653 " main.c:12 // Break at line 12 of "
655 "_regexp-break <linenum>\n"
656 " 12 // Break at line 12 of current "
658 "_regexp-break 0x<address>\n"
659 " 0x1234000 // Break at address "
661 "_regexp-break <name>\n"
662 " main // Break in 'main' after the "
664 "_regexp-break &<name>\n"
665 " &main // Break at first instruction "
667 "_regexp-break <module>`<name>\n"
668 " libc.so`malloc // Break in 'malloc' from "
670 "_regexp-break /<source-regex>/\n"
671 " /break here/ // Break on source lines in "
673 " // containing text 'break "
677 if (tbreak_regex_cmd_up) {
679 for (
size_t i = 0; i < num_regexes; i++) {
680 std::string command = break_regexes[i][1];
683 tbreak_regex_cmd_up->AddRegexCommand(break_regexes[i][0], command);
688 tbreak_regex_cmd_up->AddRegexCommand(
"^$",
"breakpoint list --full");
692 m_command_dict[std::string(tbreak_regex_cmd_sp->GetCommandName())] =
697 std::unique_ptr<CommandObjectRegexCommand> attach_regex_cmd_up(
699 *
this,
"_regexp-attach",
"Attach to process by ID or name.",
700 "_regexp-attach <pid> | <process-name>", 0,
false));
701 if (attach_regex_cmd_up) {
702 if (attach_regex_cmd_up->AddRegexCommand(
"^([0-9]+)[[:space:]]*$",
703 "process attach --pid %1") &&
704 attach_regex_cmd_up->AddRegexCommand(
705 "^(-.*|.* -.*)$",
"process attach %1") &&
708 attach_regex_cmd_up->AddRegexCommand(
"^(.+)$",
709 "process attach --name '%1'") &&
710 attach_regex_cmd_up->AddRegexCommand(
"^$",
"process attach")) {
712 m_command_dict[std::string(attach_regex_cmd_sp->GetCommandName())] =
717 std::unique_ptr<CommandObjectRegexCommand> down_regex_cmd_up(
719 "Select a newer stack frame. Defaults to "
720 "moving one frame, a numeric argument can "
721 "specify an arbitrary number.",
722 "_regexp-down [<count>]", 0,
false));
723 if (down_regex_cmd_up) {
724 if (down_regex_cmd_up->AddRegexCommand(
"^$",
"frame select -r -1") &&
725 down_regex_cmd_up->AddRegexCommand(
"^([0-9]+)$",
726 "frame select -r -%1")) {
728 m_command_dict[std::string(down_regex_cmd_sp->GetCommandName())] =
733 std::unique_ptr<CommandObjectRegexCommand> up_regex_cmd_up(
736 "Select an older stack frame. Defaults to moving one "
737 "frame, a numeric argument can specify an arbitrary number.",
738 "_regexp-up [<count>]", 0,
false));
739 if (up_regex_cmd_up) {
740 if (up_regex_cmd_up->AddRegexCommand(
"^$",
"frame select -r 1") &&
741 up_regex_cmd_up->AddRegexCommand(
"^([0-9]+)$",
"frame select -r %1")) {
748 std::unique_ptr<CommandObjectRegexCommand> display_regex_cmd_up(
750 *
this,
"_regexp-display",
751 "Evaluate an expression at every stop (see 'help target stop-hook'.)",
752 "_regexp-display expression", 0,
false));
753 if (display_regex_cmd_up) {
754 if (display_regex_cmd_up->AddRegexCommand(
755 "^(.+)$",
"target stop-hook add -o \"expr -- %1\"")) {
757 m_command_dict[std::string(display_regex_cmd_sp->GetCommandName())] =
758 display_regex_cmd_sp;
762 std::unique_ptr<CommandObjectRegexCommand> undisplay_regex_cmd_up(
764 "Stop displaying expression at every "
765 "stop (specified by stop-hook index.)",
766 "_regexp-undisplay stop-hook-number", 0,
768 if (undisplay_regex_cmd_up) {
769 if (undisplay_regex_cmd_up->AddRegexCommand(
"^([0-9]+)$",
770 "target stop-hook delete %1")) {
771 CommandObjectSP undisplay_regex_cmd_sp(undisplay_regex_cmd_up.release());
772 m_command_dict[std::string(undisplay_regex_cmd_sp->GetCommandName())] =
773 undisplay_regex_cmd_sp;
777 std::unique_ptr<CommandObjectRegexCommand> connect_gdb_remote_cmd_up(
780 "Connect to a process via remote GDB server.\n"
781 "If no host is specifed, localhost is assumed.\n"
782 "gdb-remote is an abbreviation for 'process connect --plugin "
783 "gdb-remote connect://<hostname>:<port>'\n",
784 "gdb-remote [<hostname>:]<portnum>", 0,
false));
785 if (connect_gdb_remote_cmd_up) {
786 if (connect_gdb_remote_cmd_up->AddRegexCommand(
787 "^([^:]+|\\[[0-9a-fA-F:]+.*\\]):([0-9]+)$",
788 "process connect --plugin gdb-remote connect://%1:%2") &&
789 connect_gdb_remote_cmd_up->AddRegexCommand(
791 "process connect --plugin gdb-remote connect://localhost:%1")) {
793 m_command_dict[std::string(command_sp->GetCommandName())] = command_sp;
797 std::unique_ptr<CommandObjectRegexCommand> connect_kdp_remote_cmd_up(
800 "Connect to a process via remote KDP server.\n"
801 "If no UDP port is specified, port 41139 is assumed.\n"
802 "kdp-remote is an abbreviation for 'process connect --plugin "
803 "kdp-remote udp://<hostname>:<port>'\n",
804 "kdp-remote <hostname>[:<portnum>]", 0,
false));
805 if (connect_kdp_remote_cmd_up) {
806 if (connect_kdp_remote_cmd_up->AddRegexCommand(
807 "^([^:]+:[[:digit:]]+)$",
808 "process connect --plugin kdp-remote udp://%1") &&
809 connect_kdp_remote_cmd_up->AddRegexCommand(
810 "^(.+)$",
"process connect --plugin kdp-remote udp://%1:41139")) {
812 m_command_dict[std::string(command_sp->GetCommandName())] = command_sp;
816 std::unique_ptr<CommandObjectRegexCommand> bt_regex_cmd_up(
819 "Show the current thread's call stack. Any numeric argument "
820 "displays at most that many "
821 "frames. The argument 'all' displays all threads. Use 'settings"
822 " set frame-format' to customize the printing of individual frames "
823 "and 'settings set thread-format' to customize the thread header.",
824 "bt [<digit> | all]", 0,
false));
825 if (bt_regex_cmd_up) {
830 if (bt_regex_cmd_up->AddRegexCommand(
"^([[:digit:]]+)[[:space:]]*$",
831 "thread backtrace -c %1") &&
832 bt_regex_cmd_up->AddRegexCommand(
"^-c ([[:digit:]]+)[[:space:]]*$",
833 "thread backtrace -c %1") &&
834 bt_regex_cmd_up->AddRegexCommand(
"^all[[:space:]]*$",
"thread backtrace all") &&
835 bt_regex_cmd_up->AddRegexCommand(
"^[[:space:]]*$",
"thread backtrace")) {
837 m_command_dict[std::string(command_sp->GetCommandName())] = command_sp;
841 std::unique_ptr<CommandObjectRegexCommand> list_regex_cmd_up(
843 *
this,
"_regexp-list",
844 "List relevant source code using one of several shorthand formats.",
846 "_regexp-list <file>:<line> // List around specific file/line\n"
847 "_regexp-list <line> // List current file around specified "
849 "_regexp-list <function-name> // List specified function\n"
850 "_regexp-list 0x<address> // List around specified address\n"
851 "_regexp-list -[<count>] // List previous <count> lines\n"
852 "_regexp-list // List subsequent lines",
854 if (list_regex_cmd_up) {
855 if (list_regex_cmd_up->AddRegexCommand(
"^([0-9]+)[[:space:]]*$",
856 "source list --line %1") &&
857 list_regex_cmd_up->AddRegexCommand(
858 "^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]"
860 "source list --file '%1' --line %2") &&
861 list_regex_cmd_up->AddRegexCommand(
862 "^\\*?(0x[[:xdigit:]]+)[[:space:]]*$",
863 "source list --address %1") &&
864 list_regex_cmd_up->AddRegexCommand(
"^-[[:space:]]*$",
865 "source list --reverse") &&
866 list_regex_cmd_up->AddRegexCommand(
867 "^-([[:digit:]]+)[[:space:]]*$",
868 "source list --reverse --count %1") &&
869 list_regex_cmd_up->AddRegexCommand(
"^(.+)$",
870 "source list --name \"%1\"") &&
871 list_regex_cmd_up->AddRegexCommand(
"^$",
"source list")) {
873 m_command_dict[std::string(list_regex_cmd_sp->GetCommandName())] =
878 std::unique_ptr<CommandObjectRegexCommand> env_regex_cmd_up(
880 *
this,
"_regexp-env",
881 "Shorthand for viewing and setting environment variables.",
883 "_regexp-env // Show environment\n"
884 "_regexp-env <name>=<value> // Set an environment variable",
886 if (env_regex_cmd_up) {
887 if (env_regex_cmd_up->AddRegexCommand(
"^$",
888 "settings show target.env-vars") &&
889 env_regex_cmd_up->AddRegexCommand(
"^([A-Za-z_][A-Za-z_0-9]*=.*)$",
890 "settings set target.env-vars %1")) {
897 std::unique_ptr<CommandObjectRegexCommand> jump_regex_cmd_up(
899 *
this,
"_regexp-jump",
"Set the program counter to a new address.",
901 "_regexp-jump <line>\n"
902 "_regexp-jump +<line-offset> | -<line-offset>\n"
903 "_regexp-jump <file>:<line>\n"
904 "_regexp-jump *<addr>\n",
906 if (jump_regex_cmd_up) {
907 if (jump_regex_cmd_up->AddRegexCommand(
"^\\*(.*)$",
908 "thread jump --addr %1") &&
909 jump_regex_cmd_up->AddRegexCommand(
"^([0-9]+)$",
910 "thread jump --line %1") &&
911 jump_regex_cmd_up->AddRegexCommand(
"^([^:]+):([0-9]+)$",
912 "thread jump --file %1 --line %2") &&
913 jump_regex_cmd_up->AddRegexCommand(
"^([+\\-][0-9]+)$",
914 "thread jump --by %1")) {
916 m_command_dict[std::string(jump_regex_cmd_sp->GetCommandName())] =
923 const char *cmd_str,
bool include_aliases,
StringList &matches,
928 if (include_aliases) {
937 Args &path,
bool leaf_is_command,
Status &result) {
940 auto get_multi_or_report_error =
947 if (!cmd_sp->IsUserCommand()) {
969 if (num_args == 1 && leaf_is_command) {
979 get_multi_or_report_error(cur_cmd_sp, cur_name);
980 if (cur_as_multi ==
nullptr)
983 size_t num_path_elements = num_args - (leaf_is_command ? 1 : 0);
984 for (
size_t cursor = 1; cursor < num_path_elements && cur_as_multi !=
nullptr;
988 cur_as_multi = get_multi_or_report_error(cur_cmd_sp, cur_name);
999 std::string cmd = std::string(cmd_str);
1004 command_sp = pos->second;
1010 command_sp = alias_pos->second;
1016 command_sp = pos->second;
1022 command_sp = pos->second;
1025 if (!exact && !command_sp) {
1032 if (matches ==
nullptr)
1033 matches = &local_matches;
1035 unsigned int num_cmd_matches = 0;
1036 unsigned int num_alias_matches = 0;
1037 unsigned int num_user_matches = 0;
1038 unsigned int num_user_mw_matches = 0;
1046 *matches, descriptions);
1049 if (num_cmd_matches == 1) {
1053 real_match_sp = pos->second;
1058 *matches, descriptions);
1061 if (num_alias_matches == 1) {
1065 alias_match_sp = alias_pos->second;
1070 *matches, descriptions);
1073 if (num_user_matches == 1) {
1079 user_match_sp = pos->second;
1087 if (num_user_mw_matches == 1) {
1093 user_mw_match_sp = pos->second;
1099 if (num_user_matches + num_user_mw_matches + num_cmd_matches +
1100 num_alias_matches ==
1102 if (num_cmd_matches)
1103 return real_match_sp;
1104 else if (num_alias_matches)
1105 return alias_match_sp;
1106 else if (num_user_mw_matches)
1107 return user_mw_match_sp;
1109 return user_match_sp;
1111 }
else if (matches && command_sp) {
1124 lldbassert((
this == &cmd_sp->GetCommandInterpreter()) &&
1125 "tried to add a CommandObject from a different interpreter");
1130 cmd_sp->SetIsUserCommand(
false);
1132 std::string name_sstr(name);
1135 if (!can_replace || !name_iter->second->IsRemovable())
1137 name_iter->second = cmd_sp;
1149 lldbassert((
this == &cmd_sp->GetCommandInterpreter()) &&
1150 "tried to add a CommandObject from a different interpreter");
1152 result.
SetErrorString(
"can't use the empty string for a command name");
1164 "user command \"{0}\" already exists and force replace was not set "
1165 "by --overwrite or 'settings set interpreter.require-overwrite "
1170 if (cmd_sp->IsMultiwordObject()) {
1173 "can't replace explicitly non-removable multi-word command");
1177 if (!
m_user_dict[std::string(name)]->IsRemovable()) {
1178 result.
SetErrorString(
"can't replace explicitly non-removable command");
1184 cmd_sp->SetIsUserCommand(
true);
1186 if (cmd_sp->IsMultiwordObject())
1195 bool include_aliases)
const {
1197 Args cmd_words(cmd_str);
1199 if (cmd_str.empty())
1216 for (
size_t i = 1; i < end; ++i) {
1217 if (!cmd_obj_sp->IsMultiwordObject()) {
1242 matches, descriptions)
1248 std::string cmd_str(cmd);
1250 auto found_elem = map.find(std::string(cmd));
1251 if (found_elem == map.end())
1274 StringList *matches_ptr = matches ? matches : &tmp_list;
1277 cmd_str, *matches_ptr);
1287 std::string &full_name)
const {
1291 full_name.assign(std::string(cmd));
1295 size_t num_alias_matches;
1298 if (num_alias_matches == 1) {
1301 const bool include_aliases =
false;
1302 const bool exact =
false;
1304 GetCommandSP(cmd, include_aliases, exact, ®ular_matches));
1305 if (cmd_obj_sp || regular_matches.
GetSize() > 0)
1331 llvm::StringRef args_string) {
1332 if (command_obj_sp.get())
1333 lldbassert((
this == &command_obj_sp->GetCommandInterpreter()) &&
1334 "tried to add a CommandObject from a different interpreter");
1336 std::unique_ptr<CommandAlias> command_alias_up(
1337 new CommandAlias(*
this, command_obj_sp, args_string, alias_name));
1339 if (command_alias_up && command_alias_up->IsValid()) {
1342 return command_alias_up.release();
1360 if (force || pos->second->IsRemovable()) {
1371 CommandObject::CommandMap::iterator pos =
1381 CommandObject::CommandMap::iterator pos =
1391 uint32_t cmd_types) {
1392 llvm::StringRef help_prologue(
GetDebugger().GetIOHandlerHelpPrologue());
1393 if (!help_prologue.empty()) {
1398 CommandObject::CommandMap::const_iterator pos;
1407 (pos->first.compare(0, 1,
"_") == 0))
1411 pos->second->GetHelp(), max_len);
1419 "Current command abbreviations "
1420 "(type '%shelp command alias' for more info):\n",
1428 alias_pos->second->GetHelp(), max_len);
1440 pos->second->GetHelp(), max_len);
1447 result.
AppendMessage(
"Current user-defined container commands:");
1452 pos->second->GetHelp(), max_len);
1458 "For more information on any command, type '%shelp <command-name>'.\n",
1463 llvm::StringRef &command_string) {
1469 size_t start = command_string.find_first_not_of(
k_white_space);
1473 if (start != std::string::npos) {
1476 if (end == std::string::npos)
1477 end = command_string.size();
1478 std::string cmd_word =
1479 std::string(command_string.substr(start, end - start));
1481 if (cmd_obj ==
nullptr)
1491 cmd_obj = sub_cmd_obj;
1503 end >= command_string.size())
1506 start = command_string.find_first_not_of(
k_white_space, end);
1512 command_string = command_string.substr(end);
1517 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
1521 if (pos == std::string::npos)
1530 const size_t s_len = s.size();
1532 while (offset < s_len) {
1533 size_t pos = s.find(
"--", offset);
1534 if (pos == std::string::npos)
1537 if (llvm::isSpace(s[pos - 1])) {
1540 if ((pos + 2 >= s_len) || llvm::isSpace(s[pos + 2])) {
1547 return std::string::npos;
1551 std::string &suffix,
char "e_char) {
1556 bool result =
false;
1559 if (!command_string.empty()) {
1560 const char first_char = command_string[0];
1561 if (first_char ==
'\'' || first_char ==
'"') {
1562 quote_char = first_char;
1563 const size_t end_quote_pos = command_string.find(quote_char, 1);
1564 if (end_quote_pos == std::string::npos) {
1565 command.swap(command_string);
1566 command_string.erase();
1568 command.assign(command_string, 1, end_quote_pos - 1);
1569 if (end_quote_pos + 1 < command_string.size())
1570 command_string.erase(0, command_string.find_first_not_of(
1573 command_string.erase();
1576 const size_t first_space_pos =
1578 if (first_space_pos == std::string::npos) {
1579 command.swap(command_string);
1580 command_string.erase();
1582 command.assign(command_string, 0, first_space_pos);
1583 command_string.erase(0, command_string.find_first_not_of(
1590 if (!command.empty()) {
1592 if (command[0] !=
'-' && command[0] !=
'_') {
1594 if (pos > 0 && pos != std::string::npos) {
1595 suffix.assign(command.begin() + pos, command.end());
1605 llvm::StringRef alias_name, std::string &raw_input_string,
1608 Args cmd_args(raw_input_string);
1612 if (!alias_cmd_obj || !alias_cmd_obj->
IsAlias()) {
1613 alias_result.clear();
1614 return alias_cmd_obj;
1616 std::pair<CommandObjectSP, OptionArgVectorSP> desugared =
1619 alias_cmd_obj = desugared.first.get();
1620 std::string alias_name_str = std::string(alias_name);
1623 cmd_args.
Unshift(alias_name_str);
1627 if (!option_arg_vector_sp.get()) {
1628 alias_result = std::string(result_str.
GetString());
1629 return alias_cmd_obj;
1636 for (
const auto &entry : *option_arg_vector) {
1637 std::tie(option, value_type, value) = entry;
1639 result_str.
Printf(
" %s", value.c_str());
1643 result_str.
Printf(
" %s", option.c_str());
1651 result_str.
Printf(
"%s", value.c_str());
1655 "need at least %d arguments to use "
1661 size_t strpos = raw_input_string.find(entry.
c_str());
1663 if (strpos != std::string::npos) {
1664 const size_t start_fudge = quote_char ==
'\0' ? 0 : 1;
1665 const size_t len_fudge = quote_char ==
'\0' ? 0 : 2;
1668 if (strpos < start_fudge) {
1669 result.
AppendError(
"Unmatched quote at command beginning.");
1672 llvm::StringRef arg_text = entry.
ref();
1673 if (strpos - start_fudge + arg_text.size() + len_fudge >
1674 raw_input_string.size()) {
1675 result.
AppendError(
"Unmatched quote at command end.");
1678 raw_input_string = raw_input_string.erase(
1679 strpos - start_fudge,
1682 if (quote_char ==
'\0')
1685 result_str.
Printf(
"%c%s%c", quote_char, entry.
c_str(), quote_char);
1689 alias_result = std::string(result_str.
GetString());
1690 return alias_cmd_obj;
1701 size_t start_backtick;
1703 while ((start_backtick = command.find(
'`', pos)) != std::string::npos) {
1708 if (start_backtick > 0 && command[start_backtick - 1] ==
'\\') {
1711 command.erase(start_backtick - 1, 1);
1713 pos = start_backtick;
1717 const size_t expr_content_start = start_backtick + 1;
1718 const size_t end_backtick = command.find(
'`', expr_content_start);
1720 if (end_backtick == std::string::npos) {
1725 if (end_backtick == expr_content_start) {
1727 command.erase(start_backtick, 2);
1731 std::string expr_str(command, expr_content_start,
1732 end_backtick - expr_content_start);
1738 command.erase(start_backtick, end_backtick - start_backtick + 1);
1739 command.insert(start_backtick, std::string(expr_str));
1740 pos = start_backtick + expr_str.size();
1768 expr_result_valobj_sp, options);
1772 if (expr_result_valobj_sp)
1773 expr_result_valobj_sp =
1774 expr_result_valobj_sp->GetQualifiedRepresentationIfAvailable(
1775 expr_result_valobj_sp->GetDynamicValueType(),
true);
1776 if (expr_result_valobj_sp->ResolveValue(scalar)) {
1779 const bool show_type =
false;
1780 scalar.
GetValue(value_strm, show_type);
1781 size_t value_string_size = value_strm.
GetSize();
1782 if (value_string_size) {
1783 expr_str = value_strm.
GetData();
1785 error.SetErrorStringWithFormat(
"expression value didn't result "
1786 "in a scalar value for the "
1791 error.SetErrorStringWithFormat(
"expression value didn't result "
1792 "in a scalar value for the "
1803 if (expr_result_valobj_sp)
1804 error = expr_result_valobj_sp->GetError();
1806 if (
error.Success()) {
1807 switch (expr_result) {
1809 error.SetErrorStringWithFormat(
1810 "expression setup error for the expression '%s'", expr_str.c_str());
1813 error.SetErrorStringWithFormat(
1814 "expression parse error for the expression '%s'", expr_str.c_str());
1817 error.SetErrorStringWithFormat(
1818 "expression error fetching result for the expression '%s'",
1824 error.SetErrorStringWithFormat(
1825 "expression discarded for the expression '%s'", expr_str.c_str());
1828 error.SetErrorStringWithFormat(
1829 "expression interrupted for the expression '%s'", expr_str.c_str());
1832 error.SetErrorStringWithFormat(
1833 "expression hit breakpoint for the expression '%s'",
1837 error.SetErrorStringWithFormat(
1838 "expression timed out for the expression '%s'", expr_str.c_str());
1841 error.SetErrorStringWithFormat(
"expression stop at entry point "
1842 "for debugging for the "
1847 error.SetErrorStringWithFormat(
1848 "expression thread vanished for the expression '%s'",
1862 bool status =
HandleCommand(command_line, lazy_add_to_history, result);
1870 bool force_repeat_command) {
1871 std::string command_string(command_line);
1872 std::string original_command_string(command_line);
1875 llvm::PrettyStackTraceFormat stack_trace(
"HandleCommand(command = \"%s\")",
1878 LLDB_LOGF(log,
"Processing command: %s", command_line);
1886 bool add_to_history;
1890 add_to_history = (lazy_add_to_history ==
eLazyBoolYes);
1894 bool empty_command =
false;
1895 bool comment_command =
false;
1896 if (command_string.empty())
1897 empty_command =
true;
1899 const char *k_space_characters =
"\t\n\v\f\r ";
1901 size_t non_space = command_string.find_first_not_of(k_space_characters);
1904 if (non_space == std::string::npos)
1905 empty_command =
true;
1907 comment_command =
true;
1909 llvm::StringRef search_str(command_string);
1910 search_str = search_str.drop_front(non_space);
1912 add_to_history =
false;
1913 command_string = std::string(*hist_str);
1914 original_command_string = std::string(*hist_str);
1917 command_string.c_str());
1923 if (empty_command) {
1935 command_string = command_line;
1936 original_command_string = command_line;
1942 add_to_history =
false;
1943 }
else if (comment_command) {
1983 llvm::StringRef command_name = cmd_obj ? cmd_obj->
GetCommandName() :
"<not found>";
1984 LLDB_LOGF(log,
"HandleCommand, cmd_obj : '%s'", command_name.str().c_str());
1985 LLDB_LOGF(log,
"HandleCommand, (revised) command_string: '%s'",
1986 command_string.c_str());
1987 const bool wants_raw_input =
1989 LLDB_LOGF(log,
"HandleCommand, wants_raw_input:'%s'",
1990 wants_raw_input ?
"True" :
"False");
1998 if (cmd_obj !=
nullptr) {
1999 bool generate_repeat_command = add_to_history;
2003 generate_repeat_command |= empty_command;
2008 generate_repeat_command |= force_repeat_command;
2009 if (generate_repeat_command) {
2010 Args command_args(command_string);
2011 std::optional<std::string> repeat_command =
2013 if (repeat_command) {
2014 LLDB_LOGF(log,
"Repeat command: %s", repeat_command->data());
2024 std::string remainder;
2025 const std::size_t actual_cmd_name_len = cmd_obj->
GetCommandName().size();
2026 if (actual_cmd_name_len < command_string.length())
2027 remainder = command_string.substr(actual_cmd_name_len);
2031 if (pos != 0 && pos != std::string::npos)
2032 remainder.erase(0, pos);
2035 log,
"HandleCommand, command line after removing command name(s): '%s'",
2038 cmd_obj->
Execute(remainder.c_str(), result);
2041 LLDB_LOGF(log,
"HandleCommand, command %s",
2042 (result.
Succeeded() ?
"succeeded" :
"did not succeed"));
2051 bool look_for_subcommand =
false;
2057 bool include_aliases =
true;
2068 &new_matches, &new_descriptions);
2075 look_for_subcommand =
true;
2090 if (command_object) {
2103 if (!first_arg.empty()) {
2108 request.
AddCompletion(*hist_str,
"Previous command history event",
2117std::optional<std::string>
2120 return std::nullopt;
2122 for (
int i = s - 1; i >= 0; --i) {
2124 if (entry.consume_front(line))
2127 return std::nullopt;
2131 EventSP prompt_change_event_sp(
2142 return default_answer;
2175 const char *alias_name,
2177 std::string &raw_input_string,
2185 std::string alias_name_str = alias_name;
2187 cmd_args.
Unshift(alias_name_str);
2193 if (option_arg_vector_sp.get()) {
2194 if (wants_raw_input) {
2198 size_t pos = raw_input_string.find(
" -- ");
2199 if (pos == std::string::npos) {
2201 raw_input_string.insert(0,
" -- ");
2207 std::vector<bool> used(old_size + 1,
false);
2214 for (
const auto &option_entry : *option_arg_vector) {
2215 std::tie(option, value_type, value) = option_entry;
2217 if (!wants_raw_input || (value !=
"--")) {
2241 "need at least %d arguments to use "
2249 if (strpos != std::string::npos) {
2250 raw_input_string = raw_input_string.erase(
2263 for (
auto entry : llvm::enumerate(cmd_args.
entries())) {
2264 if (!used[entry.index()] && !wants_raw_input)
2277 if (wants_raw_input) {
2293 const char *cptr = in_string;
2296 if (cptr[0] ==
'%') {
2300 if (isdigit(cptr[0])) {
2301 const char *start = cptr;
2302 while (isdigit(cptr[0]))
2307 if (cptr[0] ==
'\0')
2308 position = atoi(start);
2316 llvm::StringRef suffix = {}) {
2317 std::string init_file_name =
".lldbinit";
2318 if (!suffix.empty()) {
2319 init_file_name.append(
"-");
2320 init_file_name.append(suffix.str());
2324 llvm::sys::path::append(init_file, init_file_name);
2334 language = *main_repl_language;
2339 std::string init_file_name =
2340 (llvm::Twine(
".lldbinit-") +
2342 llvm::Twine(
"-repl"))
2345 llvm::sys::path::append(init_file, init_file_name);
2350 llvm::StringRef s =
".lldbinit";
2351 init_file.assign(s.begin(), s.end());
2383 llvm::SmallString<128> init_file;
2393 switch (should_load) {
2401 llvm::SmallString<128> home_init_file;
2403 if (llvm::sys::path::parent_path(init_file) ==
2404 llvm::sys::path::parent_path(home_init_file)) {
2424 llvm::SmallString<128> init_file;
2429 if (init_file.empty())
2433 llvm::StringRef program_name =
2434 HostInfo::GetProgramFileSpec().GetFilename().GetStringRef();
2435 llvm::SmallString<128> program_init_file;
2438 init_file = program_init_file;
2445#ifdef LLDB_GLOBAL_INIT_DIRECTORY
2447 FileSpec init_file(LLDB_GLOBAL_INIT_DIRECTORY);
2461 return prefix ==
nullptr ?
"" : prefix;
2466 if (prefer_target_platform) {
2480 TargetSP target_sp = exe_ctx.GetTargetSP();
2484 ProcessSP process_sp(target_sp->GetProcessSP());
2491 for (
const auto &thread_sp : process_sp->GetThreadList().Threads()) {
2492 StopInfoSP stop_info = thread_sp->GetStopInfo();
2500 const StopReason reason = stop_info->GetStopReason();
2507 const auto stop_signal =
static_cast<int32_t
>(stop_info->GetValue());
2509 if (!signals_sp || !signals_sp->SignalIsValid(stop_signal))
2513 const auto sigint_num = signals_sp->GetSignalNumberFromName(
"SIGINT");
2514 const auto sigstop_num = signals_sp->GetSignalNumberFromName(
"SIGSTOP");
2515 if ((stop_signal != sigint_num) && (stop_signal != sigstop_num))
2538 size_t num_lines = commands.
GetSize();
2550 for (
size_t idx = 0; idx < num_lines; idx++) {
2579 if (!success || !tmp_result.
Succeeded()) {
2581 if (error_msg.empty())
2582 error_msg =
"<unknown error>.\n";
2585 "Aborting reading of commands after command #%" PRIu64
2586 ": '%s' failed with %s",
2587 (uint64_t)idx, cmd, error_msg.str().c_str());
2592 "Command #%" PRIu64
" '%s' failed with %s", (uint64_t)idx + 1, cmd,
2593 error_msg.str().c_str());
2614 if (idx != num_lines - 1)
2616 "Aborting reading of commands after command #%" PRIu64
2617 ": '%s' continued the target.\n",
2618 (uint64_t)idx + 1, cmd);
2621 " '%s' continued the target.\n",
2622 (uint64_t)idx + 1, cmd);
2634 if (idx != num_lines - 1)
2636 "Aborting reading of commands after command #%" PRIu64
2637 ": '%s' stopped with a signal or exception.\n",
2638 (uint64_t)idx + 1, cmd);
2641 "Command #%" PRIu64
" '%s' stopped with a signal or exception.\n",
2642 (uint64_t)idx + 1, cmd);
2679 "Error reading commands from file %s - file not found.\n",
2684 std::string cmd_file_path = cmd_file.
GetPath();
2685 auto input_file_up =
2687 if (!input_file_up) {
2688 std::string
error = llvm::toString(input_file_up.takeError());
2690 "error: an error occurred read file '{0}': {1}\n", cmd_file_path,
2691 llvm::fmt_consume(input_file_up.takeError()));
2694 FileSP input_file_sp =
FileSP(std::move(input_file_up.get()));
2781 cmd_file_path.c_str());
2797 debugger.
GetPrompt(), llvm::StringRef(),
2827 llvm::StringRef prefix,
2828 llvm::StringRef help_text) {
2831 size_t line_width_max = max_columns - prefix.size();
2832 if (line_width_max < 16)
2833 line_width_max = help_text.size() + prefix.size();
2836 bool prefixed_yet =
false;
2838 if (help_text.empty())
2839 help_text =
"No help text";
2840 while (!help_text.empty()) {
2842 if (!prefixed_yet) {
2844 prefixed_yet =
true;
2849 llvm::StringRef this_line = help_text.substr(0, line_width_max);
2852 std::size_t first_newline = this_line.find_first_of(
"\n");
2855 std::size_t last_space = llvm::StringRef::npos;
2856 if (this_line.size() != help_text.size())
2857 last_space = this_line.find_last_of(
" \t");
2860 this_line = this_line.substr(0, std::min(first_newline, last_space));
2865 help_text = help_text.drop_front(this_line.size()).ltrim();
2871 llvm::StringRef word_text,
2872 llvm::StringRef separator,
2873 llvm::StringRef help_text,
2874 size_t max_word_len) {
2876 prefix_stream.
Printf(
" %-*s %*s ", (
int)max_word_len, word_text.data(),
2877 (
int)separator.size(), separator.data());
2882 llvm::StringRef separator,
2883 llvm::StringRef help_text,
2884 uint32_t max_word_len) {
2885 int indent_size = max_word_len + separator.size() + 2;
2890 text_strm.
Printf(
"%-*s ", (
int)max_word_len, word_text.data());
2891 text_strm << separator <<
" " << help_text;
2895 llvm::StringRef text = text_strm.
GetString();
2897 uint32_t chars_left = max_columns;
2899 auto nextWordLength = [](llvm::StringRef S) {
2900 size_t pos = S.find(
' ');
2901 return pos == llvm::StringRef::npos ? S.size() : pos;
2904 while (!text.empty()) {
2905 if (text.front() ==
'\n' ||
2906 (text.front() ==
' ' && nextWordLength(text.ltrim(
' ')) > chars_left)) {
2909 chars_left = max_columns - indent_size;
2910 if (text.front() ==
'\n')
2911 text = text.drop_front();
2913 text = text.ltrim(
' ');
2917 text = text.drop_front();
2926 llvm::StringRef search_word,
StringList &commands_found,
2928 for (
const auto &pair : command_map) {
2929 llvm::StringRef command_name = pair.first;
2932 const bool search_short_help =
true;
2933 const bool search_long_help =
false;
2934 const bool search_syntax =
false;
2935 const bool search_options =
false;
2936 if (command_name.contains_insensitive(search_word) ||
2938 search_long_help, search_syntax,
2947 multiword_cmd->GetSubcommandDictionary());
2948 for (
const auto &subcommand_name : subcommands_found) {
2949 std::string qualified_name =
2950 (command_name +
" " + subcommand_name).str();
2960 bool search_builtin_commands,
2961 bool search_user_commands,
2962 bool search_alias_commands,
2963 bool search_user_mw_commands) {
2964 CommandObject::CommandMap::const_iterator pos;
2966 if (search_builtin_commands)
2970 if (search_user_commands)
2974 if (search_user_mw_commands)
2978 if (search_alias_commands)
3033 bool was_interrupted =
3036 return was_interrupted;
3040 llvm::StringRef str,
3046 bool had_output = !str.empty();
3047 while (!str.empty()) {
3048 llvm::StringRef line;
3049 std::tie(line, str) = str.split(
'\n');
3051 std::lock_guard<std::recursive_mutex> guard(io_handler.
GetOutputMutex());
3052 stream->Write(line.data(), line.size());
3053 stream->Write(
"\n", 1);
3057 std::lock_guard<std::recursive_mutex> guard(io_handler.
GetOutputMutex());
3060 stream->Printf(
"\n... Interrupted.\n");
3065 llvm::StringRef line,
const Flags &io_handler_flags)
const {
3069 llvm::StringRef command = line.trim();
3070 if (command.empty())
3080 std::string &line) {
3086 if (!is_interactive) {
3098 std::lock_guard<std::recursive_mutex> guard(io_handler.
GetOutputMutex());
3100 "%s%s\n", io_handler.
GetPrompt(), line.c_str());
3107 bool pushed_exe_ctx =
false;
3110 pushed_exe_ctx =
true;
3112 auto finalize = llvm::make_scope_exit([
this, pushed_exe_ctx]() {
3121 if ((result.Succeeded() &&
3127 if (!result.GetImmediateOutputStream()) {
3128 llvm::StringRef output = result.GetOutputData();
3133 if (!result.GetImmediateErrorStream()) {
3134 llvm::StringRef
error = result.GetErrorData();
3141 switch (result.GetStatus()) {
3170 result.GetDidChangeProcessState() &&
3195 if (script_interpreter) {
3204 if (output_file == std::nullopt || output_file->empty()) {
3205 std::string now = llvm::to_string(std::chrono::system_clock::now());
3206 std::replace(now.begin(), now.end(),
' ',
'_');
3207 const std::string file_name =
"lldb_session_" + now +
".log";
3212 save_location = HostInfo::GetGlobalTempDir();
3216 output_file = save_location.
GetPath();
3219 auto error_out = [&](llvm::StringRef error_message, std::string description) {
3221 output_file, description);
3223 "Failed to save session's transcripts to {0}!", *output_file);
3234 return error_out(
"Unable to create file",
3235 llvm::toString(opened_file.takeError()));
3237 FileUP file = std::move(opened_file.get());
3244 return error_out(
"Unable to write to destination file",
3245 "Bytes written do not match transcript size.");
3249 output_file->c_str());
3253 error = file->GetFileSpec(
const_cast<FileSpec &
>(file_spec));
3254 if (
error.Success()) {
3280 llvm::StringRef(prompt),
3287 if (io_handler_sp) {
3288 io_handler_sp->SetUserData(baton);
3299 llvm::StringRef(prompt),
3306 if (io_handler_sp) {
3307 io_handler_sp->SetUserData(baton);
3365 bool force_create =
true;
3393 std::string scratch_command(command_line);
3397 bool wants_raw_input =
false;
3398 std::string next_word;
3402 char quote_char =
'\0';
3405 if (cmd_obj ==
nullptr) {
3406 std::string full_name;
3409 bool is_real_command =
3410 (!is_alias) || (cmd_obj !=
nullptr && !cmd_obj->
IsAlias());
3411 if (!is_real_command) {
3413 std::string alias_result;
3416 revised_command_line.
Printf(
"%s", alias_result.c_str());
3423 revised_command_line.
Printf(
"%s", cmd_name.str().c_str());
3426 revised_command_line.
Printf(
"%s", next_word.c_str());
3437 revised_command_line.
Clear();
3438 revised_command_line.
Printf(
"%s", sub_cmd_name.str().c_str());
3439 cmd_obj = sub_cmd_obj;
3443 revised_command_line.
Printf(
" %c%s%s%c", quote_char,
3444 next_word.c_str(), suffix.c_str(),
3447 revised_command_line.
Printf(
" %s%s", next_word.c_str(),
3453 revised_command_line.
Printf(
" %c%s%s%c", quote_char,
3454 next_word.c_str(), suffix.c_str(),
3457 revised_command_line.
Printf(
" %s%s", next_word.c_str(),
3463 if (cmd_obj ==
nullptr) {
3464 const size_t num_matches = matches.
GetSize();
3467 error_msg.
Printf(
"Ambiguous command '%s'. Possible matches:\n",
3470 for (uint32_t i = 0; i < num_matches; ++i) {
3484 if (!suffix.empty()) {
3486 "command '%s' did not recognize '%s%s%s' as valid (subcommand "
3487 "might be invalid).\n",
3489 next_word.empty() ?
"" : next_word.c_str(),
3490 next_word.empty() ?
" -- " :
" ", suffix.c_str());
3496 if (!suffix.empty()) {
3497 switch (suffix[0]) {
3502 if (command_options &&
3504 std::string gdb_format_option(
"--gdb-format=");
3505 gdb_format_option += (suffix.c_str() + 1);
3507 std::string cmd = std::string(revised_command_line.
GetString());
3509 if (arg_terminator_idx != std::string::npos) {
3512 gdb_format_option.append(1,
' ');
3513 cmd.insert(arg_terminator_idx, gdb_format_option);
3514 revised_command_line.
Clear();
3517 revised_command_line.
Printf(
" %s", gdb_format_option.c_str());
3519 if (wants_raw_input &&
3524 "the '%s' command doesn't support the --gdb-format option\n",
3533 "unknown command shorthand suffix: '%s'\n", suffix.c_str());
3538 if (scratch_command.empty())
3542 if (!scratch_command.empty())
3543 revised_command_line.
Printf(
" %s", scratch_command.c_str());
3545 if (cmd_obj !=
nullptr)
3546 command_line = std::string(revised_command_line.
GetString());
3552 llvm::json::Object stats;
3554 stats.try_emplace(command_usage.getKey(), command_usage.getValue());
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
@ eHandleCommandFlagStopOnCrash
@ eHandleCommandFlagEchoCommentCommand
@ eHandleCommandFlagStopOnError
@ eHandleCommandFlagStopOnContinue
@ eHandleCommandFlagPrintErrors
@ eHandleCommandFlagEchoCommand
@ eHandleCommandFlagPrintResult
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)
static llvm::raw_ostream & error(Stream &strm)
#define INTERRUPT_REQUESTED(debugger,...)
This handy define will keep you from having to generate a report for the interruption by hand.
#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()
CommandUsageMap m_command_usages
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.
llvm::json::Value GetStatistics()
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 void Execute(const char *args_string, CommandReturnObject &result)=0
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 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=0600)
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 SetErrorStringWithFormatv(const char *format, Args &&... args)
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
std::shared_ptr< lldb_private::OptionValueProperties > OptionValuePropertiesSP
std::shared_ptr< lldb_private::IOHandler > IOHandlerSP
std::shared_ptr< lldb_private::CommandObject > CommandObjectSP
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
std::unique_ptr< lldb_private::File > FileUP
@ 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.
std::shared_ptr< lldb_private::UnixSignals > UnixSignalsSP
std::shared_ptr< lldb_private::Platform > PlatformSP
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
std::shared_ptr< lldb_private::Process > ProcessSP
std::shared_ptr< lldb_private::Event > EventSP
@ eReturnStatusSuccessContinuingResult
@ eReturnStatusSuccessContinuingNoResult
@ eReturnStatusSuccessFinishResult
@ eReturnStatusSuccessFinishNoResult
std::shared_ptr< lldb_private::StreamFile > StreamFileSP
std::shared_ptr< lldb_private::StopInfo > StopInfoSP
StopReason
Thread stop reasons.
@ eStopReasonInstrumentation
@ eStopReasonProcessorTrace
std::shared_ptr< lldb_private::Target > TargetSP
std::shared_ptr< lldb_private::File > FileSP
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.