1 //===-- CommandInterpreter.cpp ----------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
14 #include "CommandObjectScript.h"
15 #include "lldb/Interpreter/CommandObjectRegexCommand.h"
17 #include "Commands/CommandObjectApropos.h"
18 #include "Commands/CommandObjectBreakpoint.h"
19 #include "Commands/CommandObjectBugreport.h"
20 #include "Commands/CommandObjectCommands.h"
21 #include "Commands/CommandObjectDisassemble.h"
22 #include "Commands/CommandObjectExpression.h"
23 #include "Commands/CommandObjectFrame.h"
24 #include "Commands/CommandObjectGUI.h"
25 #include "Commands/CommandObjectHelp.h"
26 #include "Commands/CommandObjectLanguage.h"
27 #include "Commands/CommandObjectLog.h"
28 #include "Commands/CommandObjectMemory.h"
29 #include "Commands/CommandObjectPlatform.h"
30 #include "Commands/CommandObjectPlugin.h"
31 #include "Commands/CommandObjectProcess.h"
32 #include "Commands/CommandObjectQuit.h"
33 #include "Commands/CommandObjectRegister.h"
34 #include "Commands/CommandObjectReproducer.h"
35 #include "Commands/CommandObjectSettings.h"
36 #include "Commands/CommandObjectSource.h"
37 #include "Commands/CommandObjectStats.h"
38 #include "Commands/CommandObjectTarget.h"
39 #include "Commands/CommandObjectThread.h"
40 #include "Commands/CommandObjectType.h"
41 #include "Commands/CommandObjectVersion.h"
42 #include "Commands/CommandObjectWatchpoint.h"
44 #include "lldb/Core/Debugger.h"
45 #include "lldb/Core/PluginManager.h"
46 #include "lldb/Core/StreamFile.h"
47 #include "lldb/Utility/Log.h"
48 #include "lldb/Utility/State.h"
49 #include "lldb/Utility/Stream.h"
50 #include "lldb/Utility/Timer.h"
52 #ifndef LLDB_DISABLE_LIBEDIT
53 #include "lldb/Host/Editline.h"
55 #include "lldb/Host/Host.h"
56 #include "lldb/Host/HostInfo.h"
58 #include "lldb/Interpreter/CommandCompletions.h"
59 #include "lldb/Interpreter/CommandInterpreter.h"
60 #include "lldb/Interpreter/CommandReturnObject.h"
61 #include "lldb/Interpreter/OptionValueProperties.h"
62 #include "lldb/Interpreter/Options.h"
63 #include "lldb/Interpreter/Property.h"
64 #include "lldb/Utility/Args.h"
66 #include "lldb/Target/Process.h"
67 #include "lldb/Target/TargetList.h"
68 #include "lldb/Target/Thread.h"
70 #include "llvm/ADT/STLExtras.h"
71 #include "llvm/ADT/SmallString.h"
72 #include "llvm/Support/Path.h"
73 #include "llvm/Support/PrettyStackTrace.h"
76 using namespace lldb_private;
78 static const char *k_white_space = " \t\v";
80 static constexpr bool NoGlobalSetting = true;
81 static constexpr uintptr_t DefaultValueTrue = true;
82 static constexpr uintptr_t DefaultValueFalse = false;
83 static constexpr const char *NoCStrDefault = nullptr;
84 static constexpr const char *InitFileWarning =
85 "There is a .lldbinit file in the current directory which is not being "
87 "To silence this warning without sourcing in the local .lldbinit,\n"
88 "add the following to the lldbinit file in your home directory:\n"
89 " settings set target.load-cwd-lldbinit false\n"
90 "To allow lldb to source .lldbinit files in the current working "
92 "set the value of this variable to true. Only do so if you understand "
94 "accept the security risk.";
96 static constexpr PropertyDefinition g_properties[] = {
97 {"expand-regex-aliases", OptionValue::eTypeBoolean, NoGlobalSetting,
98 DefaultValueFalse, NoCStrDefault, {},
99 "If true, regular expression alias commands will show the "
100 "expanded command that will be executed. This can be used to "
101 "debug new regular expression alias commands."},
102 {"prompt-on-quit", OptionValue::eTypeBoolean, NoGlobalSetting,
103 DefaultValueTrue, NoCStrDefault, {},
104 "If true, LLDB will prompt you before quitting if there are any live "
105 "processes being debugged. If false, LLDB will quit without asking in any "
107 {"stop-command-source-on-error", OptionValue::eTypeBoolean, NoGlobalSetting,
108 DefaultValueTrue, NoCStrDefault, {},
109 "If true, LLDB will stop running a 'command source' "
110 "script upon encountering an error."},
111 {"space-repl-prompts", OptionValue::eTypeBoolean, NoGlobalSetting,
112 DefaultValueFalse, NoCStrDefault, {},
113 "If true, blank lines will be printed between between REPL submissions."},
114 {"echo-commands", OptionValue::eTypeBoolean, NoGlobalSetting,
115 DefaultValueTrue, NoCStrDefault, {},
116 "If true, commands will be echoed before they are evaluated."},
117 {"echo-comment-commands", OptionValue::eTypeBoolean, NoGlobalSetting,
118 DefaultValueTrue, NoCStrDefault, {},
119 "If true, commands will be echoed even if they are pure comment lines."}};
122 ePropertyExpandRegexAliases = 0,
123 ePropertyPromptOnQuit = 1,
124 ePropertyStopCmdSourceOnError = 2,
125 eSpaceReplPrompts = 3,
127 eEchoCommentCommands = 5
130 ConstString &CommandInterpreter::GetStaticBroadcasterClass() {
131 static ConstString class_name("lldb.commandInterpreter");
135 CommandInterpreter::CommandInterpreter(Debugger &debugger,
136 bool synchronous_execution)
137 : Broadcaster(debugger.GetBroadcasterManager(),
138 CommandInterpreter::GetStaticBroadcasterClass().AsCString()),
139 Properties(OptionValuePropertiesSP(
140 new OptionValueProperties(ConstString("interpreter")))),
141 IOHandlerDelegate(IOHandlerDelegate::Completion::LLDBCommand),
142 m_debugger(debugger), m_synchronous_execution(synchronous_execution),
143 m_skip_lldbinit_files(false), m_skip_app_init_files(false),
144 m_command_io_handler_sp(), m_comment_char('#'),
145 m_batch_command_mode(false), m_truncation_warning(eNoTruncation),
146 m_command_source_depth(0), m_num_errors(0), m_quit_requested(false),
147 m_stopped_for_crash(false) {
148 SetEventName(eBroadcastBitThreadShouldExit, "thread-should-exit");
149 SetEventName(eBroadcastBitResetPrompt, "reset-prompt");
150 SetEventName(eBroadcastBitQuitCommandReceived, "quit");
151 CheckInWithManager();
152 m_collection_sp->Initialize(g_properties);
155 bool CommandInterpreter::GetExpandRegexAliases() const {
156 const uint32_t idx = ePropertyExpandRegexAliases;
157 return m_collection_sp->GetPropertyAtIndexAsBoolean(
158 nullptr, idx, g_properties[idx].default_uint_value != 0);
161 bool CommandInterpreter::GetPromptOnQuit() const {
162 const uint32_t idx = ePropertyPromptOnQuit;
163 return m_collection_sp->GetPropertyAtIndexAsBoolean(
164 nullptr, idx, g_properties[idx].default_uint_value != 0);
167 void CommandInterpreter::SetPromptOnQuit(bool b) {
168 const uint32_t idx = ePropertyPromptOnQuit;
169 m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
172 bool CommandInterpreter::GetEchoCommands() const {
173 const uint32_t idx = eEchoCommands;
174 return m_collection_sp->GetPropertyAtIndexAsBoolean(
175 nullptr, idx, g_properties[idx].default_uint_value != 0);
178 void CommandInterpreter::SetEchoCommands(bool b) {
179 const uint32_t idx = eEchoCommands;
180 m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
183 bool CommandInterpreter::GetEchoCommentCommands() const {
184 const uint32_t idx = eEchoCommentCommands;
185 return m_collection_sp->GetPropertyAtIndexAsBoolean(
186 nullptr, idx, g_properties[idx].default_uint_value != 0);
189 void CommandInterpreter::SetEchoCommentCommands(bool b) {
190 const uint32_t idx = eEchoCommentCommands;
191 m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
194 void CommandInterpreter::AllowExitCodeOnQuit(bool allow) {
195 m_allow_exit_code = allow;
197 m_quit_exit_code.reset();
200 bool CommandInterpreter::SetQuitExitCode(int exit_code) {
201 if (!m_allow_exit_code)
203 m_quit_exit_code = exit_code;
207 int CommandInterpreter::GetQuitExitCode(bool &exited) const {
208 exited = m_quit_exit_code.hasValue();
210 return *m_quit_exit_code;
214 void CommandInterpreter::ResolveCommand(const char *command_line,
215 CommandReturnObject &result) {
216 std::string command = command_line;
217 if (ResolveCommandImpl(command, result) != nullptr) {
218 result.AppendMessageWithFormat("%s", command.c_str());
219 result.SetStatus(eReturnStatusSuccessFinishResult);
223 bool CommandInterpreter::GetStopCmdSourceOnError() const {
224 const uint32_t idx = ePropertyStopCmdSourceOnError;
225 return m_collection_sp->GetPropertyAtIndexAsBoolean(
226 nullptr, idx, g_properties[idx].default_uint_value != 0);
229 bool CommandInterpreter::GetSpaceReplPrompts() const {
230 const uint32_t idx = eSpaceReplPrompts;
231 return m_collection_sp->GetPropertyAtIndexAsBoolean(
232 nullptr, idx, g_properties[idx].default_uint_value != 0);
235 void CommandInterpreter::Initialize() {
236 static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
237 Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION);
239 CommandReturnObject result;
241 LoadCommandDictionary();
243 // An alias arguments vector to reuse - reset it before use...
244 OptionArgVectorSP alias_arguments_vector_sp(new OptionArgVector);
246 // Set up some initial aliases.
247 CommandObjectSP cmd_obj_sp = GetCommandSPExact("quit", false);
249 AddAlias("q", cmd_obj_sp);
250 AddAlias("exit", cmd_obj_sp);
253 cmd_obj_sp = GetCommandSPExact("_regexp-attach", false);
255 AddAlias("attach", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
257 cmd_obj_sp = GetCommandSPExact("process detach", false);
259 AddAlias("detach", cmd_obj_sp);
262 cmd_obj_sp = GetCommandSPExact("process continue", false);
264 AddAlias("c", cmd_obj_sp);
265 AddAlias("continue", cmd_obj_sp);
268 cmd_obj_sp = GetCommandSPExact("_regexp-break", false);
270 AddAlias("b", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
272 cmd_obj_sp = GetCommandSPExact("_regexp-tbreak", false);
274 AddAlias("tbreak", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
276 cmd_obj_sp = GetCommandSPExact("thread step-inst", false);
278 AddAlias("stepi", cmd_obj_sp);
279 AddAlias("si", cmd_obj_sp);
282 cmd_obj_sp = GetCommandSPExact("thread step-inst-over", false);
284 AddAlias("nexti", cmd_obj_sp);
285 AddAlias("ni", cmd_obj_sp);
288 cmd_obj_sp = GetCommandSPExact("thread step-in", false);
290 AddAlias("s", cmd_obj_sp);
291 AddAlias("step", cmd_obj_sp);
292 CommandAlias *sif_alias = AddAlias(
293 "sif", cmd_obj_sp, "--end-linenumber block --step-in-target %1");
295 sif_alias->SetHelp("Step through the current block, stopping if you step "
296 "directly into a function whose name matches the "
297 "TargetFunctionName.");
298 sif_alias->SetSyntax("sif <TargetFunctionName>");
302 cmd_obj_sp = GetCommandSPExact("thread step-over", false);
304 AddAlias("n", cmd_obj_sp);
305 AddAlias("next", cmd_obj_sp);
308 cmd_obj_sp = GetCommandSPExact("thread step-out", false);
310 AddAlias("finish", cmd_obj_sp);
313 cmd_obj_sp = GetCommandSPExact("frame select", false);
315 AddAlias("f", cmd_obj_sp);
318 cmd_obj_sp = GetCommandSPExact("thread select", false);
320 AddAlias("t", cmd_obj_sp);
323 cmd_obj_sp = GetCommandSPExact("_regexp-jump", false);
325 AddAlias("j", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
326 AddAlias("jump", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
329 cmd_obj_sp = GetCommandSPExact("_regexp-list", false);
331 AddAlias("l", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
332 AddAlias("list", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
335 cmd_obj_sp = GetCommandSPExact("_regexp-env", false);
337 AddAlias("env", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
339 cmd_obj_sp = GetCommandSPExact("memory read", false);
341 AddAlias("x", cmd_obj_sp);
343 cmd_obj_sp = GetCommandSPExact("_regexp-up", false);
345 AddAlias("up", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
347 cmd_obj_sp = GetCommandSPExact("_regexp-down", false);
349 AddAlias("down", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
351 cmd_obj_sp = GetCommandSPExact("_regexp-display", false);
353 AddAlias("display", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
355 cmd_obj_sp = GetCommandSPExact("disassemble", false);
357 AddAlias("dis", cmd_obj_sp);
359 cmd_obj_sp = GetCommandSPExact("disassemble", false);
361 AddAlias("di", cmd_obj_sp);
363 cmd_obj_sp = GetCommandSPExact("_regexp-undisplay", false);
365 AddAlias("undisplay", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
367 cmd_obj_sp = GetCommandSPExact("_regexp-bt", false);
369 AddAlias("bt", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
371 cmd_obj_sp = GetCommandSPExact("target create", false);
373 AddAlias("file", cmd_obj_sp);
375 cmd_obj_sp = GetCommandSPExact("target modules", false);
377 AddAlias("image", cmd_obj_sp);
379 alias_arguments_vector_sp = std::make_shared<OptionArgVector>();
381 cmd_obj_sp = GetCommandSPExact("expression", false);
383 AddAlias("p", cmd_obj_sp, "--")->SetHelpLong("");
384 AddAlias("print", cmd_obj_sp, "--")->SetHelpLong("");
385 AddAlias("call", cmd_obj_sp, "--")->SetHelpLong("");
386 if (auto po = AddAlias("po", cmd_obj_sp, "-O --")) {
387 po->SetHelp("Evaluate an expression on the current thread. Displays any "
388 "returned value with formatting "
389 "controlled by the type's author.");
392 AddAlias("parray", cmd_obj_sp, "--element-count %1 --")->SetHelpLong("");
393 AddAlias("poarray", cmd_obj_sp,
394 "--object-description --element-count %1 --")
398 cmd_obj_sp = GetCommandSPExact("process kill", false);
400 AddAlias("kill", cmd_obj_sp);
403 cmd_obj_sp = GetCommandSPExact("process launch", false);
405 alias_arguments_vector_sp = std::make_shared<OptionArgVector>();
406 #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
407 AddAlias("r", cmd_obj_sp, "--");
408 AddAlias("run", cmd_obj_sp, "--");
410 #if defined(__APPLE__)
411 std::string shell_option;
412 shell_option.append("--shell-expand-args");
413 shell_option.append(" true");
414 shell_option.append(" --");
415 AddAlias("r", cmd_obj_sp, "--shell-expand-args true --");
416 AddAlias("run", cmd_obj_sp, "--shell-expand-args true --");
418 StreamString defaultshell;
419 defaultshell.Printf("--shell=%s --",
420 HostInfo::GetDefaultShell().GetPath().c_str());
421 AddAlias("r", cmd_obj_sp, defaultshell.GetString());
422 AddAlias("run", cmd_obj_sp, defaultshell.GetString());
427 cmd_obj_sp = GetCommandSPExact("target symbols add", false);
429 AddAlias("add-dsym", cmd_obj_sp);
432 cmd_obj_sp = GetCommandSPExact("breakpoint set", false);
434 AddAlias("rbreak", cmd_obj_sp, "--func-regex %1");
437 cmd_obj_sp = GetCommandSPExact("frame variable", false);
439 AddAlias("v", cmd_obj_sp);
440 AddAlias("var", cmd_obj_sp);
441 AddAlias("vo", cmd_obj_sp, "--object-description");
444 cmd_obj_sp = GetCommandSPExact("register", false);
446 AddAlias("re", cmd_obj_sp);
450 void CommandInterpreter::Clear() {
451 m_command_io_handler_sp.reset();
454 const char *CommandInterpreter::ProcessEmbeddedScriptCommands(const char *arg) {
455 // This function has not yet been implemented.
457 // Look for any embedded script command
459 // get interpreter object from the command dictionary,
460 // call execute_one_command on it,
461 // get the results as a string,
462 // substitute that string for current stuff.
467 void CommandInterpreter::LoadCommandDictionary() {
468 static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
469 Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION);
471 lldb::ScriptLanguage script_language = m_debugger.GetScriptLanguage();
473 m_command_dict["apropos"] = CommandObjectSP(new CommandObjectApropos(*this));
474 m_command_dict["breakpoint"] =
475 CommandObjectSP(new CommandObjectMultiwordBreakpoint(*this));
476 m_command_dict["bugreport"] =
477 CommandObjectSP(new CommandObjectMultiwordBugreport(*this));
478 m_command_dict["command"] =
479 CommandObjectSP(new CommandObjectMultiwordCommands(*this));
480 m_command_dict["disassemble"] =
481 CommandObjectSP(new CommandObjectDisassemble(*this));
482 m_command_dict["expression"] =
483 CommandObjectSP(new CommandObjectExpression(*this));
484 m_command_dict["frame"] =
485 CommandObjectSP(new CommandObjectMultiwordFrame(*this));
486 m_command_dict["gui"] = CommandObjectSP(new CommandObjectGUI(*this));
487 m_command_dict["help"] = CommandObjectSP(new CommandObjectHelp(*this));
488 m_command_dict["log"] = CommandObjectSP(new CommandObjectLog(*this));
489 m_command_dict["memory"] = CommandObjectSP(new CommandObjectMemory(*this));
490 m_command_dict["platform"] =
491 CommandObjectSP(new CommandObjectPlatform(*this));
492 m_command_dict["plugin"] = CommandObjectSP(new CommandObjectPlugin(*this));
493 m_command_dict["process"] =
494 CommandObjectSP(new CommandObjectMultiwordProcess(*this));
495 m_command_dict["quit"] = CommandObjectSP(new CommandObjectQuit(*this));
496 m_command_dict["register"] =
497 CommandObjectSP(new CommandObjectRegister(*this));
498 m_command_dict["reproducer"] =
499 CommandObjectSP(new CommandObjectReproducer(*this));
500 m_command_dict["script"] =
501 CommandObjectSP(new CommandObjectScript(*this, script_language));
502 m_command_dict["settings"] =
503 CommandObjectSP(new CommandObjectMultiwordSettings(*this));
504 m_command_dict["source"] =
505 CommandObjectSP(new CommandObjectMultiwordSource(*this));
506 m_command_dict["statistics"] = CommandObjectSP(new CommandObjectStats(*this));
507 m_command_dict["target"] =
508 CommandObjectSP(new CommandObjectMultiwordTarget(*this));
509 m_command_dict["thread"] =
510 CommandObjectSP(new CommandObjectMultiwordThread(*this));
511 m_command_dict["type"] = CommandObjectSP(new CommandObjectType(*this));
512 m_command_dict["version"] = CommandObjectSP(new CommandObjectVersion(*this));
513 m_command_dict["watchpoint"] =
514 CommandObjectSP(new CommandObjectMultiwordWatchpoint(*this));
515 m_command_dict["language"] =
516 CommandObjectSP(new CommandObjectLanguage(*this));
518 const char *break_regexes[][2] = {
519 {"^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$",
520 "breakpoint set --file '%1' --line %2"},
521 {"^/([^/]+)/$", "breakpoint set --source-pattern-regexp '%1'"},
522 {"^([[:digit:]]+)[[:space:]]*$", "breakpoint set --line %1"},
523 {"^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "breakpoint set --address %1"},
524 {"^[\"']?([-+]?\\[.*\\])[\"']?[[:space:]]*$",
525 "breakpoint set --name '%1'"},
526 {"^(-.*)$", "breakpoint set %1"},
527 {"^(.*[^[:space:]])`(.*[^[:space:]])[[:space:]]*$",
528 "breakpoint set --name '%2' --shlib '%1'"},
529 {"^\\&(.*[^[:space:]])[[:space:]]*$",
530 "breakpoint set --name '%1' --skip-prologue=0"},
531 {"^[\"']?(.*[^[:space:]\"'])[\"']?[[:space:]]*$",
532 "breakpoint set --name '%1'"}};
534 size_t num_regexes = llvm::array_lengthof(break_regexes);
536 std::unique_ptr<CommandObjectRegexCommand> break_regex_cmd_up(
537 new CommandObjectRegexCommand(
538 *this, "_regexp-break",
539 "Set a breakpoint using one of several shorthand formats.",
541 "_regexp-break <filename>:<linenum>\n"
542 " main.c:12 // Break at line 12 of "
544 "_regexp-break <linenum>\n"
545 " 12 // Break at line 12 of current "
547 "_regexp-break 0x<address>\n"
548 " 0x1234000 // Break at address "
550 "_regexp-break <name>\n"
551 " main // Break in 'main' after the "
553 "_regexp-break &<name>\n"
554 " &main // Break at first instruction "
556 "_regexp-break <module>`<name>\n"
557 " libc.so`malloc // Break in 'malloc' from "
559 "_regexp-break /<source-regex>/\n"
560 " /break here/ // Break on source lines in "
562 " // containing text 'break "
565 CommandCompletions::eSymbolCompletion |
566 CommandCompletions::eSourceFileCompletion,
569 if (break_regex_cmd_up) {
571 for (size_t i = 0; i < num_regexes; i++) {
572 success = break_regex_cmd_up->AddRegexCommand(break_regexes[i][0],
573 break_regexes[i][1]);
578 break_regex_cmd_up->AddRegexCommand("^$", "breakpoint list --full");
581 CommandObjectSP break_regex_cmd_sp(break_regex_cmd_up.release());
582 m_command_dict[break_regex_cmd_sp->GetCommandName()] = break_regex_cmd_sp;
586 std::unique_ptr<CommandObjectRegexCommand> tbreak_regex_cmd_up(
587 new CommandObjectRegexCommand(
588 *this, "_regexp-tbreak",
589 "Set a one-shot breakpoint using one of several shorthand formats.",
591 "_regexp-break <filename>:<linenum>\n"
592 " main.c:12 // Break at line 12 of "
594 "_regexp-break <linenum>\n"
595 " 12 // Break at line 12 of current "
597 "_regexp-break 0x<address>\n"
598 " 0x1234000 // Break at address "
600 "_regexp-break <name>\n"
601 " main // Break in 'main' after the "
603 "_regexp-break &<name>\n"
604 " &main // Break at first instruction "
606 "_regexp-break <module>`<name>\n"
607 " libc.so`malloc // Break in 'malloc' from "
609 "_regexp-break /<source-regex>/\n"
610 " /break here/ // Break on source lines in "
612 " // containing text 'break "
615 CommandCompletions::eSymbolCompletion |
616 CommandCompletions::eSourceFileCompletion,
619 if (tbreak_regex_cmd_up) {
621 for (size_t i = 0; i < num_regexes; i++) {
622 // If you add a resultant command string longer than 1024 characters be
623 // sure to increase the size of this buffer.
626 snprintf(buffer, 1024, "%s %s", break_regexes[i][1], "-o 1");
627 lldbassert(num_printed < 1024);
628 UNUSED_IF_ASSERT_DISABLED(num_printed);
630 tbreak_regex_cmd_up->AddRegexCommand(break_regexes[i][0], buffer);
635 tbreak_regex_cmd_up->AddRegexCommand("^$", "breakpoint list --full");
638 CommandObjectSP tbreak_regex_cmd_sp(tbreak_regex_cmd_up.release());
639 m_command_dict[tbreak_regex_cmd_sp->GetCommandName()] =
644 std::unique_ptr<CommandObjectRegexCommand> attach_regex_cmd_up(
645 new CommandObjectRegexCommand(
646 *this, "_regexp-attach", "Attach to process by ID or name.",
647 "_regexp-attach <pid> | <process-name>", 2, 0, false));
648 if (attach_regex_cmd_up) {
649 if (attach_regex_cmd_up->AddRegexCommand("^([0-9]+)[[:space:]]*$",
650 "process attach --pid %1") &&
651 attach_regex_cmd_up->AddRegexCommand(
652 "^(-.*|.* -.*)$", "process attach %1") && // Any options that are
653 // specified get passed to
655 attach_regex_cmd_up->AddRegexCommand("^(.+)$",
656 "process attach --name '%1'") &&
657 attach_regex_cmd_up->AddRegexCommand("^$", "process attach")) {
658 CommandObjectSP attach_regex_cmd_sp(attach_regex_cmd_up.release());
659 m_command_dict[attach_regex_cmd_sp->GetCommandName()] =
664 std::unique_ptr<CommandObjectRegexCommand> down_regex_cmd_up(
665 new CommandObjectRegexCommand(*this, "_regexp-down",
666 "Select a newer stack frame. Defaults to "
667 "moving one frame, a numeric argument can "
668 "specify an arbitrary number.",
669 "_regexp-down [<count>]", 2, 0, false));
670 if (down_regex_cmd_up) {
671 if (down_regex_cmd_up->AddRegexCommand("^$", "frame select -r -1") &&
672 down_regex_cmd_up->AddRegexCommand("^([0-9]+)$",
673 "frame select -r -%1")) {
674 CommandObjectSP down_regex_cmd_sp(down_regex_cmd_up.release());
675 m_command_dict[down_regex_cmd_sp->GetCommandName()] = down_regex_cmd_sp;
679 std::unique_ptr<CommandObjectRegexCommand> up_regex_cmd_up(
680 new CommandObjectRegexCommand(
682 "Select an older stack frame. Defaults to moving one "
683 "frame, a numeric argument can specify an arbitrary number.",
684 "_regexp-up [<count>]", 2, 0, false));
685 if (up_regex_cmd_up) {
686 if (up_regex_cmd_up->AddRegexCommand("^$", "frame select -r 1") &&
687 up_regex_cmd_up->AddRegexCommand("^([0-9]+)$", "frame select -r %1")) {
688 CommandObjectSP up_regex_cmd_sp(up_regex_cmd_up.release());
689 m_command_dict[up_regex_cmd_sp->GetCommandName()] = up_regex_cmd_sp;
693 std::unique_ptr<CommandObjectRegexCommand> display_regex_cmd_up(
694 new CommandObjectRegexCommand(
695 *this, "_regexp-display",
696 "Evaluate an expression at every stop (see 'help target stop-hook'.)",
697 "_regexp-display expression", 2, 0, false));
698 if (display_regex_cmd_up) {
699 if (display_regex_cmd_up->AddRegexCommand(
700 "^(.+)$", "target stop-hook add -o \"expr -- %1\"")) {
701 CommandObjectSP display_regex_cmd_sp(display_regex_cmd_up.release());
702 m_command_dict[display_regex_cmd_sp->GetCommandName()] =
703 display_regex_cmd_sp;
707 std::unique_ptr<CommandObjectRegexCommand> undisplay_regex_cmd_up(
708 new CommandObjectRegexCommand(*this, "_regexp-undisplay",
709 "Stop displaying expression at every "
710 "stop (specified by stop-hook index.)",
711 "_regexp-undisplay stop-hook-number", 2, 0,
713 if (undisplay_regex_cmd_up) {
714 if (undisplay_regex_cmd_up->AddRegexCommand("^([0-9]+)$",
715 "target stop-hook delete %1")) {
716 CommandObjectSP undisplay_regex_cmd_sp(undisplay_regex_cmd_up.release());
717 m_command_dict[undisplay_regex_cmd_sp->GetCommandName()] =
718 undisplay_regex_cmd_sp;
722 std::unique_ptr<CommandObjectRegexCommand> connect_gdb_remote_cmd_up(
723 new CommandObjectRegexCommand(
725 "Connect to a process via remote GDB server. "
726 "If no host is specifed, localhost is assumed.",
727 "gdb-remote [<hostname>:]<portnum>", 2, 0, false));
728 if (connect_gdb_remote_cmd_up) {
729 if (connect_gdb_remote_cmd_up->AddRegexCommand(
730 "^([^:]+|\\[[0-9a-fA-F:]+.*\\]):([0-9]+)$",
731 "process connect --plugin gdb-remote connect://%1:%2") &&
732 connect_gdb_remote_cmd_up->AddRegexCommand(
734 "process connect --plugin gdb-remote connect://localhost:%1")) {
735 CommandObjectSP command_sp(connect_gdb_remote_cmd_up.release());
736 m_command_dict[command_sp->GetCommandName()] = command_sp;
740 std::unique_ptr<CommandObjectRegexCommand> connect_kdp_remote_cmd_up(
741 new CommandObjectRegexCommand(
743 "Connect to a process via remote KDP server. "
744 "If no UDP port is specified, port 41139 is "
746 "kdp-remote <hostname>[:<portnum>]", 2, 0, false));
747 if (connect_kdp_remote_cmd_up) {
748 if (connect_kdp_remote_cmd_up->AddRegexCommand(
749 "^([^:]+:[[:digit:]]+)$",
750 "process connect --plugin kdp-remote udp://%1") &&
751 connect_kdp_remote_cmd_up->AddRegexCommand(
752 "^(.+)$", "process connect --plugin kdp-remote udp://%1:41139")) {
753 CommandObjectSP command_sp(connect_kdp_remote_cmd_up.release());
754 m_command_dict[command_sp->GetCommandName()] = command_sp;
758 std::unique_ptr<CommandObjectRegexCommand> bt_regex_cmd_up(
759 new CommandObjectRegexCommand(
761 "Show the current thread's call stack. Any numeric argument "
762 "displays at most that many "
763 "frames. The argument 'all' displays all threads. Use 'settings"
764 " set frame-format' to customize the printing of individual frames "
765 "and 'settings set thread-format' to customize the thread header.",
766 "bt [<digit> | all]", 2, 0, false));
767 if (bt_regex_cmd_up) {
768 // accept but don't document "bt -c <number>" -- before bt was a regex
769 // command if you wanted to backtrace three frames you would do "bt -c 3"
770 // but the intention is to have this emulate the gdb "bt" command and so
771 // now "bt 3" is the preferred form, in line with gdb.
772 if (bt_regex_cmd_up->AddRegexCommand("^([[:digit:]]+)[[:space:]]*$",
773 "thread backtrace -c %1") &&
774 bt_regex_cmd_up->AddRegexCommand("^-c ([[:digit:]]+)[[:space:]]*$",
775 "thread backtrace -c %1") &&
776 bt_regex_cmd_up->AddRegexCommand("^all[[:space:]]*$", "thread backtrace all") &&
777 bt_regex_cmd_up->AddRegexCommand("^[[:space:]]*$", "thread backtrace")) {
778 CommandObjectSP command_sp(bt_regex_cmd_up.release());
779 m_command_dict[command_sp->GetCommandName()] = command_sp;
783 std::unique_ptr<CommandObjectRegexCommand> list_regex_cmd_up(
784 new CommandObjectRegexCommand(
785 *this, "_regexp-list",
786 "List relevant source code using one of several shorthand formats.",
788 "_regexp-list <file>:<line> // List around specific file/line\n"
789 "_regexp-list <line> // List current file around specified "
791 "_regexp-list <function-name> // List specified function\n"
792 "_regexp-list 0x<address> // List around specified address\n"
793 "_regexp-list -[<count>] // List previous <count> lines\n"
794 "_regexp-list // List subsequent lines",
795 2, CommandCompletions::eSourceFileCompletion, false));
796 if (list_regex_cmd_up) {
797 if (list_regex_cmd_up->AddRegexCommand("^([0-9]+)[[:space:]]*$",
798 "source list --line %1") &&
799 list_regex_cmd_up->AddRegexCommand(
800 "^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]"
802 "source list --file '%1' --line %2") &&
803 list_regex_cmd_up->AddRegexCommand(
804 "^\\*?(0x[[:xdigit:]]+)[[:space:]]*$",
805 "source list --address %1") &&
806 list_regex_cmd_up->AddRegexCommand("^-[[:space:]]*$",
807 "source list --reverse") &&
808 list_regex_cmd_up->AddRegexCommand(
809 "^-([[:digit:]]+)[[:space:]]*$",
810 "source list --reverse --count %1") &&
811 list_regex_cmd_up->AddRegexCommand("^(.+)$",
812 "source list --name \"%1\"") &&
813 list_regex_cmd_up->AddRegexCommand("^$", "source list")) {
814 CommandObjectSP list_regex_cmd_sp(list_regex_cmd_up.release());
815 m_command_dict[list_regex_cmd_sp->GetCommandName()] = list_regex_cmd_sp;
819 std::unique_ptr<CommandObjectRegexCommand> env_regex_cmd_up(
820 new CommandObjectRegexCommand(
821 *this, "_regexp-env",
822 "Shorthand for viewing and setting environment variables.",
824 "_regexp-env // Show environment\n"
825 "_regexp-env <name>=<value> // Set an environment variable",
827 if (env_regex_cmd_up) {
828 if (env_regex_cmd_up->AddRegexCommand("^$",
829 "settings show target.env-vars") &&
830 env_regex_cmd_up->AddRegexCommand("^([A-Za-z_][A-Za-z_0-9]*=.*)$",
831 "settings set target.env-vars %1")) {
832 CommandObjectSP env_regex_cmd_sp(env_regex_cmd_up.release());
833 m_command_dict[env_regex_cmd_sp->GetCommandName()] = env_regex_cmd_sp;
837 std::unique_ptr<CommandObjectRegexCommand> jump_regex_cmd_up(
838 new CommandObjectRegexCommand(
839 *this, "_regexp-jump", "Set the program counter to a new address.",
841 "_regexp-jump <line>\n"
842 "_regexp-jump +<line-offset> | -<line-offset>\n"
843 "_regexp-jump <file>:<line>\n"
844 "_regexp-jump *<addr>\n",
846 if (jump_regex_cmd_up) {
847 if (jump_regex_cmd_up->AddRegexCommand("^\\*(.*)$",
848 "thread jump --addr %1") &&
849 jump_regex_cmd_up->AddRegexCommand("^([0-9]+)$",
850 "thread jump --line %1") &&
851 jump_regex_cmd_up->AddRegexCommand("^([^:]+):([0-9]+)$",
852 "thread jump --file %1 --line %2") &&
853 jump_regex_cmd_up->AddRegexCommand("^([+\\-][0-9]+)$",
854 "thread jump --by %1")) {
855 CommandObjectSP jump_regex_cmd_sp(jump_regex_cmd_up.release());
856 m_command_dict[jump_regex_cmd_sp->GetCommandName()] = jump_regex_cmd_sp;
861 int CommandInterpreter::GetCommandNamesMatchingPartialString(
862 const char *cmd_str, bool include_aliases, StringList &matches,
863 StringList &descriptions) {
864 AddNamesMatchingPartialString(m_command_dict, cmd_str, matches,
867 if (include_aliases) {
868 AddNamesMatchingPartialString(m_alias_dict, cmd_str, matches,
872 return matches.GetSize();
876 CommandInterpreter::GetCommandSP(llvm::StringRef cmd_str, bool include_aliases,
877 bool exact, StringList *matches,
878 StringList *descriptions) const {
879 CommandObjectSP command_sp;
881 std::string cmd = cmd_str;
884 auto pos = m_command_dict.find(cmd);
885 if (pos != m_command_dict.end())
886 command_sp = pos->second;
889 if (include_aliases && HasAliases()) {
890 auto alias_pos = m_alias_dict.find(cmd);
891 if (alias_pos != m_alias_dict.end())
892 command_sp = alias_pos->second;
895 if (HasUserCommands()) {
896 auto pos = m_user_dict.find(cmd);
897 if (pos != m_user_dict.end())
898 command_sp = pos->second;
901 if (!exact && !command_sp) {
902 // We will only get into here if we didn't find any exact matches.
904 CommandObjectSP user_match_sp, alias_match_sp, real_match_sp;
906 StringList local_matches;
907 if (matches == nullptr)
908 matches = &local_matches;
910 unsigned int num_cmd_matches = 0;
911 unsigned int num_alias_matches = 0;
912 unsigned int num_user_matches = 0;
914 // Look through the command dictionaries one by one, and if we get only one
915 // match from any of them in toto, then return that, otherwise return an
916 // empty CommandObjectSP and the list of matches.
919 num_cmd_matches = AddNamesMatchingPartialString(m_command_dict, cmd_str,
920 *matches, descriptions);
923 if (num_cmd_matches == 1) {
924 cmd.assign(matches->GetStringAtIndex(0));
925 auto pos = m_command_dict.find(cmd);
926 if (pos != m_command_dict.end())
927 real_match_sp = pos->second;
930 if (include_aliases && HasAliases()) {
931 num_alias_matches = AddNamesMatchingPartialString(m_alias_dict, cmd_str,
932 *matches, descriptions);
935 if (num_alias_matches == 1) {
936 cmd.assign(matches->GetStringAtIndex(num_cmd_matches));
937 auto alias_pos = m_alias_dict.find(cmd);
938 if (alias_pos != m_alias_dict.end())
939 alias_match_sp = alias_pos->second;
942 if (HasUserCommands()) {
943 num_user_matches = AddNamesMatchingPartialString(m_user_dict, cmd_str,
944 *matches, descriptions);
947 if (num_user_matches == 1) {
949 matches->GetStringAtIndex(num_cmd_matches + num_alias_matches));
951 auto pos = m_user_dict.find(cmd);
952 if (pos != m_user_dict.end())
953 user_match_sp = pos->second;
956 // If we got exactly one match, return that, otherwise return the match
959 if (num_user_matches + num_cmd_matches + num_alias_matches == 1) {
961 return real_match_sp;
962 else if (num_alias_matches)
963 return alias_match_sp;
965 return user_match_sp;
967 } else if (matches && command_sp) {
968 matches->AppendString(cmd_str);
970 descriptions->AppendString(command_sp->GetHelp());
976 bool CommandInterpreter::AddCommand(llvm::StringRef name,
977 const lldb::CommandObjectSP &cmd_sp,
980 lldbassert((this == &cmd_sp->GetCommandInterpreter()) &&
981 "tried to add a CommandObject from a different interpreter");
986 std::string name_sstr(name);
987 auto name_iter = m_command_dict.find(name_sstr);
988 if (name_iter != m_command_dict.end()) {
989 if (!can_replace || !name_iter->second->IsRemovable())
991 name_iter->second = cmd_sp;
993 m_command_dict[name_sstr] = cmd_sp;
998 bool CommandInterpreter::AddUserCommand(llvm::StringRef name,
999 const lldb::CommandObjectSP &cmd_sp,
1002 lldbassert((this == &cmd_sp->GetCommandInterpreter()) &&
1003 "tried to add a CommandObject from a different interpreter");
1005 if (!name.empty()) {
1006 // do not allow replacement of internal commands
1007 if (CommandExists(name)) {
1010 if (!m_command_dict[name]->IsRemovable())
1014 if (UserCommandExists(name)) {
1017 if (!m_user_dict[name]->IsRemovable())
1021 m_user_dict[name] = cmd_sp;
1027 CommandObjectSP CommandInterpreter::GetCommandSPExact(llvm::StringRef cmd_str,
1028 bool include_aliases) const {
1029 Args cmd_words(cmd_str); // Break up the command string into words, in case
1030 // it's a multi-word command.
1031 CommandObjectSP ret_val; // Possibly empty return value.
1033 if (cmd_str.empty())
1036 if (cmd_words.GetArgumentCount() == 1)
1037 return GetCommandSP(cmd_str, include_aliases, true, nullptr);
1039 // We have a multi-word command (seemingly), so we need to do more work.
1040 // First, get the cmd_obj_sp for the first word in the command.
1041 CommandObjectSP cmd_obj_sp = GetCommandSP(llvm::StringRef(cmd_words.GetArgumentAtIndex(0)),
1042 include_aliases, true, nullptr);
1043 if (cmd_obj_sp.get() != nullptr) {
1044 // Loop through the rest of the words in the command (everything passed
1045 // in was supposed to be part of a command name), and find the
1046 // appropriate sub-command SP for each command word....
1047 size_t end = cmd_words.GetArgumentCount();
1048 for (size_t j = 1; j < end; ++j) {
1049 if (cmd_obj_sp->IsMultiwordObject()) {
1051 cmd_obj_sp->GetSubcommandSP(cmd_words.GetArgumentAtIndex(j));
1052 if (cmd_obj_sp.get() == nullptr)
1053 // The sub-command name was invalid. Fail and return the empty
1057 // We have more words in the command name, but we don't have a
1058 // multiword object. Fail and return empty 'ret_val'.
1061 // We successfully looped through all the command words and got valid
1062 // command objects for them. Assign the last object retrieved to
1064 ret_val = cmd_obj_sp;
1071 CommandInterpreter::GetCommandObject(llvm::StringRef cmd_str,
1072 StringList *matches,
1073 StringList *descriptions) const {
1074 CommandObject *command_obj =
1075 GetCommandSP(cmd_str, false, true, matches, descriptions).get();
1077 // If we didn't find an exact match to the command string in the commands,
1078 // look in the aliases.
1083 command_obj = GetCommandSP(cmd_str, true, true, matches, descriptions).get();
1088 // If there wasn't an exact match then look for an inexact one in just the
1090 command_obj = GetCommandSP(cmd_str, false, false, nullptr).get();
1092 // Finally, if there wasn't an inexact match among the commands, look for an
1093 // inexact match in both the commands and aliases.
1097 matches->AppendString(command_obj->GetCommandName());
1099 descriptions->AppendString(command_obj->GetHelp());
1103 return GetCommandSP(cmd_str, true, false, matches, descriptions).get();
1106 bool CommandInterpreter::CommandExists(llvm::StringRef cmd) const {
1107 return m_command_dict.find(cmd) != m_command_dict.end();
1110 bool CommandInterpreter::GetAliasFullName(llvm::StringRef cmd,
1111 std::string &full_name) const {
1112 bool exact_match = (m_alias_dict.find(cmd) != m_alias_dict.end());
1114 full_name.assign(cmd);
1118 size_t num_alias_matches;
1120 AddNamesMatchingPartialString(m_alias_dict, cmd, matches);
1121 if (num_alias_matches == 1) {
1122 // Make sure this isn't shadowing a command in the regular command space:
1123 StringList regular_matches;
1124 const bool include_aliases = false;
1125 const bool exact = false;
1126 CommandObjectSP cmd_obj_sp(
1127 GetCommandSP(cmd, include_aliases, exact, ®ular_matches));
1128 if (cmd_obj_sp || regular_matches.GetSize() > 0)
1131 full_name.assign(matches.GetStringAtIndex(0));
1139 bool CommandInterpreter::AliasExists(llvm::StringRef cmd) const {
1140 return m_alias_dict.find(cmd) != m_alias_dict.end();
1143 bool CommandInterpreter::UserCommandExists(llvm::StringRef cmd) const {
1144 return m_user_dict.find(cmd) != m_user_dict.end();
1148 CommandInterpreter::AddAlias(llvm::StringRef alias_name,
1149 lldb::CommandObjectSP &command_obj_sp,
1150 llvm::StringRef args_string) {
1151 if (command_obj_sp.get())
1152 lldbassert((this == &command_obj_sp->GetCommandInterpreter()) &&
1153 "tried to add a CommandObject from a different interpreter");
1155 std::unique_ptr<CommandAlias> command_alias_up(
1156 new CommandAlias(*this, command_obj_sp, args_string, alias_name));
1158 if (command_alias_up && command_alias_up->IsValid()) {
1159 m_alias_dict[alias_name] = CommandObjectSP(command_alias_up.get());
1160 return command_alias_up.release();
1166 bool CommandInterpreter::RemoveAlias(llvm::StringRef alias_name) {
1167 auto pos = m_alias_dict.find(alias_name);
1168 if (pos != m_alias_dict.end()) {
1169 m_alias_dict.erase(pos);
1175 bool CommandInterpreter::RemoveCommand(llvm::StringRef cmd) {
1176 auto pos = m_command_dict.find(cmd);
1177 if (pos != m_command_dict.end()) {
1178 if (pos->second->IsRemovable()) {
1179 // Only regular expression objects or python commands are removable
1180 m_command_dict.erase(pos);
1186 bool CommandInterpreter::RemoveUser(llvm::StringRef alias_name) {
1187 CommandObject::CommandMap::iterator pos = m_user_dict.find(alias_name);
1188 if (pos != m_user_dict.end()) {
1189 m_user_dict.erase(pos);
1195 void CommandInterpreter::GetHelp(CommandReturnObject &result,
1196 uint32_t cmd_types) {
1197 llvm::StringRef help_prologue(GetDebugger().GetIOHandlerHelpPrologue());
1198 if (!help_prologue.empty()) {
1199 OutputFormattedHelpText(result.GetOutputStream(), llvm::StringRef(),
1203 CommandObject::CommandMap::const_iterator pos;
1204 size_t max_len = FindLongestCommandWord(m_command_dict);
1206 if ((cmd_types & eCommandTypesBuiltin) == eCommandTypesBuiltin) {
1207 result.AppendMessage("Debugger commands:");
1208 result.AppendMessage("");
1210 for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos) {
1211 if (!(cmd_types & eCommandTypesHidden) &&
1212 (pos->first.compare(0, 1, "_") == 0))
1215 OutputFormattedHelpText(result.GetOutputStream(), pos->first, "--",
1216 pos->second->GetHelp(), max_len);
1218 result.AppendMessage("");
1221 if (!m_alias_dict.empty() &&
1222 ((cmd_types & eCommandTypesAliases) == eCommandTypesAliases)) {
1223 result.AppendMessageWithFormat(
1224 "Current command abbreviations "
1225 "(type '%shelp command alias' for more info):\n",
1226 GetCommandPrefix());
1227 result.AppendMessage("");
1228 max_len = FindLongestCommandWord(m_alias_dict);
1230 for (auto alias_pos = m_alias_dict.begin(); alias_pos != m_alias_dict.end();
1232 OutputFormattedHelpText(result.GetOutputStream(), alias_pos->first, "--",
1233 alias_pos->second->GetHelp(), max_len);
1235 result.AppendMessage("");
1238 if (!m_user_dict.empty() &&
1239 ((cmd_types & eCommandTypesUserDef) == eCommandTypesUserDef)) {
1240 result.AppendMessage("Current user-defined commands:");
1241 result.AppendMessage("");
1242 max_len = FindLongestCommandWord(m_user_dict);
1243 for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos) {
1244 OutputFormattedHelpText(result.GetOutputStream(), pos->first, "--",
1245 pos->second->GetHelp(), max_len);
1247 result.AppendMessage("");
1250 result.AppendMessageWithFormat(
1251 "For more information on any command, type '%shelp <command-name>'.\n",
1252 GetCommandPrefix());
1255 CommandObject *CommandInterpreter::GetCommandObjectForCommand(
1256 llvm::StringRef &command_string) {
1257 // This function finds the final, lowest-level, alias-resolved command object
1258 // whose 'Execute' function will eventually be invoked by the given command
1261 CommandObject *cmd_obj = nullptr;
1262 size_t start = command_string.find_first_not_of(k_white_space);
1266 if (start != std::string::npos) {
1267 // Get the next word from command_string.
1268 end = command_string.find_first_of(k_white_space, start);
1269 if (end == std::string::npos)
1270 end = command_string.size();
1271 std::string cmd_word = command_string.substr(start, end - start);
1273 if (cmd_obj == nullptr)
1274 // Since cmd_obj is NULL we are on our first time through this loop.
1275 // Check to see if cmd_word is a valid command or alias.
1276 cmd_obj = GetCommandObject(cmd_word);
1277 else if (cmd_obj->IsMultiwordObject()) {
1278 // Our current object is a multi-word object; see if the cmd_word is a
1279 // valid sub-command for our object.
1280 CommandObject *sub_cmd_obj =
1281 cmd_obj->GetSubcommandObject(cmd_word.c_str());
1283 cmd_obj = sub_cmd_obj;
1284 else // cmd_word was not a valid sub-command word, so we are done
1287 // We have a cmd_obj and it is not a multi-word object, so we are done.
1290 // If we didn't find a valid command object, or our command object is not
1291 // a multi-word object, or we are at the end of the command_string, then
1292 // we are done. Otherwise, find the start of the next word.
1294 if (!cmd_obj || !cmd_obj->IsMultiwordObject() ||
1295 end >= command_string.size())
1298 start = command_string.find_first_not_of(k_white_space, end);
1300 // Unable to find any more words.
1304 command_string = command_string.substr(end);
1308 static const char *k_valid_command_chars =
1309 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
1310 static void StripLeadingSpaces(std::string &s) {
1312 size_t pos = s.find_first_not_of(k_white_space);
1313 if (pos == std::string::npos)
1321 static size_t FindArgumentTerminator(const std::string &s) {
1322 const size_t s_len = s.size();
1324 while (offset < s_len) {
1325 size_t pos = s.find("--", offset);
1326 if (pos == std::string::npos)
1329 if (isspace(s[pos - 1])) {
1330 // Check if the string ends "\s--" (where \s is a space character) or
1331 // if we have "\s--\s".
1332 if ((pos + 2 >= s_len) || isspace(s[pos + 2])) {
1339 return std::string::npos;
1342 static bool ExtractCommand(std::string &command_string, std::string &command,
1343 std::string &suffix, char "e_char) {
1346 StripLeadingSpaces(command_string);
1348 bool result = false;
1351 if (!command_string.empty()) {
1352 const char first_char = command_string[0];
1353 if (first_char == '\'' || first_char == '"') {
1354 quote_char = first_char;
1355 const size_t end_quote_pos = command_string.find(quote_char, 1);
1356 if (end_quote_pos == std::string::npos) {
1357 command.swap(command_string);
1358 command_string.erase();
1360 command.assign(command_string, 1, end_quote_pos - 1);
1361 if (end_quote_pos + 1 < command_string.size())
1362 command_string.erase(0, command_string.find_first_not_of(
1363 k_white_space, end_quote_pos + 1));
1365 command_string.erase();
1368 const size_t first_space_pos =
1369 command_string.find_first_of(k_white_space);
1370 if (first_space_pos == std::string::npos) {
1371 command.swap(command_string);
1372 command_string.erase();
1374 command.assign(command_string, 0, first_space_pos);
1375 command_string.erase(0, command_string.find_first_not_of(
1376 k_white_space, first_space_pos));
1382 if (!command.empty()) {
1383 // actual commands can't start with '-' or '_'
1384 if (command[0] != '-' && command[0] != '_') {
1385 size_t pos = command.find_first_not_of(k_valid_command_chars);
1386 if (pos > 0 && pos != std::string::npos) {
1387 suffix.assign(command.begin() + pos, command.end());
1396 CommandObject *CommandInterpreter::BuildAliasResult(
1397 llvm::StringRef alias_name, std::string &raw_input_string,
1398 std::string &alias_result, CommandReturnObject &result) {
1399 CommandObject *alias_cmd_obj = nullptr;
1400 Args cmd_args(raw_input_string);
1401 alias_cmd_obj = GetCommandObject(alias_name);
1402 StreamString result_str;
1404 if (!alias_cmd_obj || !alias_cmd_obj->IsAlias()) {
1405 alias_result.clear();
1406 return alias_cmd_obj;
1408 std::pair<CommandObjectSP, OptionArgVectorSP> desugared =
1409 ((CommandAlias *)alias_cmd_obj)->Desugar();
1410 OptionArgVectorSP option_arg_vector_sp = desugared.second;
1411 alias_cmd_obj = desugared.first.get();
1412 std::string alias_name_str = alias_name;
1413 if ((cmd_args.GetArgumentCount() == 0) ||
1414 (alias_name_str != cmd_args.GetArgumentAtIndex(0)))
1415 cmd_args.Unshift(alias_name_str);
1417 result_str.Printf("%s", alias_cmd_obj->GetCommandName().str().c_str());
1419 if (!option_arg_vector_sp.get()) {
1420 alias_result = result_str.GetString();
1421 return alias_cmd_obj;
1423 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
1428 for (const auto &entry : *option_arg_vector) {
1429 std::tie(option, value_type, value) = entry;
1430 if (option == "<argument>") {
1431 result_str.Printf(" %s", value.c_str());
1435 result_str.Printf(" %s", option.c_str());
1436 if (value_type == OptionParser::eNoArgument)
1439 if (value_type != OptionParser::eOptionalArgument)
1440 result_str.Printf(" ");
1441 int index = GetOptionArgumentPosition(value.c_str());
1443 result_str.Printf("%s", value.c_str());
1444 else if (static_cast<size_t>(index) >= cmd_args.GetArgumentCount()) {
1446 result.AppendErrorWithFormat("Not enough arguments provided; you "
1447 "need at least %d arguments to use "
1450 result.SetStatus(eReturnStatusFailed);
1453 size_t strpos = raw_input_string.find(cmd_args.GetArgumentAtIndex(index));
1454 if (strpos != std::string::npos)
1455 raw_input_string = raw_input_string.erase(
1456 strpos, strlen(cmd_args.GetArgumentAtIndex(index)));
1457 result_str.Printf("%s", cmd_args.GetArgumentAtIndex(index));
1461 alias_result = result_str.GetString();
1462 return alias_cmd_obj;
1465 Status CommandInterpreter::PreprocessCommand(std::string &command) {
1466 // The command preprocessor needs to do things to the command line before any
1467 // parsing of arguments or anything else is done. The only current stuff that
1468 // gets preprocessed is anything enclosed in backtick ('`') characters is
1469 // evaluated as an expression and the result of the expression must be a
1470 // scalar that can be substituted into the command. An example would be:
1471 // (lldb) memory read `$rsp + 20`
1472 Status error; // Status for any expressions that might not evaluate
1473 size_t start_backtick;
1475 while ((start_backtick = command.find('`', pos)) != std::string::npos) {
1476 // Stop if an error was encountered during the previous iteration.
1480 if (start_backtick > 0 && command[start_backtick - 1] == '\\') {
1481 // The backtick was preceded by a '\' character, remove the slash and
1482 // don't treat the backtick as the start of an expression.
1483 command.erase(start_backtick - 1, 1);
1484 // No need to add one to start_backtick since we just deleted a char.
1485 pos = start_backtick;
1489 const size_t expr_content_start = start_backtick + 1;
1490 const size_t end_backtick = command.find('`', expr_content_start);
1492 if (end_backtick == std::string::npos) {
1493 // Stop if there's no end backtick.
1497 if (end_backtick == expr_content_start) {
1498 // Skip over empty expression. (two backticks in a row)
1499 command.erase(start_backtick, 2);
1503 std::string expr_str(command, expr_content_start,
1504 end_backtick - expr_content_start);
1506 ExecutionContext exe_ctx(GetExecutionContext());
1507 Target *target = exe_ctx.GetTargetPtr();
1509 // Get a dummy target to allow for calculator mode while processing
1510 // backticks. This also helps break the infinite loop caused when target is
1513 target = m_debugger.GetDummyTarget();
1518 ValueObjectSP expr_result_valobj_sp;
1520 EvaluateExpressionOptions options;
1521 options.SetCoerceToId(false);
1522 options.SetUnwindOnError(true);
1523 options.SetIgnoreBreakpoints(true);
1524 options.SetKeepInMemory(false);
1525 options.SetTryAllThreads(true);
1526 options.SetTimeout(llvm::None);
1528 ExpressionResults expr_result =
1529 target->EvaluateExpression(expr_str.c_str(), exe_ctx.GetFramePtr(),
1530 expr_result_valobj_sp, options);
1532 if (expr_result == eExpressionCompleted) {
1534 if (expr_result_valobj_sp)
1535 expr_result_valobj_sp =
1536 expr_result_valobj_sp->GetQualifiedRepresentationIfAvailable(
1537 expr_result_valobj_sp->GetDynamicValueType(), true);
1538 if (expr_result_valobj_sp->ResolveValue(scalar)) {
1539 command.erase(start_backtick, end_backtick - start_backtick + 1);
1540 StreamString value_strm;
1541 const bool show_type = false;
1542 scalar.GetValue(&value_strm, show_type);
1543 size_t value_string_size = value_strm.GetSize();
1544 if (value_string_size) {
1545 command.insert(start_backtick, value_strm.GetString());
1546 pos = start_backtick + value_string_size;
1549 error.SetErrorStringWithFormat("expression value didn't result "
1550 "in a scalar value for the "
1556 error.SetErrorStringWithFormat("expression value didn't result "
1557 "in a scalar value for the "
1566 if (expr_result_valobj_sp)
1567 error = expr_result_valobj_sp->GetError();
1569 if (error.Success()) {
1570 switch (expr_result) {
1571 case eExpressionSetupError:
1572 error.SetErrorStringWithFormat(
1573 "expression setup error for the expression '%s'", expr_str.c_str());
1575 case eExpressionParseError:
1576 error.SetErrorStringWithFormat(
1577 "expression parse error for the expression '%s'", expr_str.c_str());
1579 case eExpressionResultUnavailable:
1580 error.SetErrorStringWithFormat(
1581 "expression error fetching result for the expression '%s'",
1584 case eExpressionCompleted:
1586 case eExpressionDiscarded:
1587 error.SetErrorStringWithFormat(
1588 "expression discarded for the expression '%s'", expr_str.c_str());
1590 case eExpressionInterrupted:
1591 error.SetErrorStringWithFormat(
1592 "expression interrupted for the expression '%s'", expr_str.c_str());
1594 case eExpressionHitBreakpoint:
1595 error.SetErrorStringWithFormat(
1596 "expression hit breakpoint for the expression '%s'",
1599 case eExpressionTimedOut:
1600 error.SetErrorStringWithFormat(
1601 "expression timed out for the expression '%s'", expr_str.c_str());
1603 case eExpressionStoppedForDebug:
1604 error.SetErrorStringWithFormat("expression stop at entry point "
1605 "for debugging for the "
1615 bool CommandInterpreter::HandleCommand(const char *command_line,
1616 LazyBool lazy_add_to_history,
1617 CommandReturnObject &result,
1618 ExecutionContext *override_context,
1619 bool repeat_on_empty_command,
1620 bool no_context_switching)
1624 std::string command_string(command_line);
1625 std::string original_command_string(command_line);
1627 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_COMMANDS));
1628 llvm::PrettyStackTraceFormat stack_trace("HandleCommand(command = \"%s\")",
1632 log->Printf("Processing command: %s", command_line);
1634 static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
1635 Timer scoped_timer(func_cat, "Handling command: %s.", command_line);
1637 if (!no_context_switching)
1638 UpdateExecutionContext(override_context);
1640 if (WasInterrupted()) {
1641 result.AppendError("interrupted");
1642 result.SetStatus(eReturnStatusFailed);
1646 bool add_to_history;
1647 if (lazy_add_to_history == eLazyBoolCalculate)
1648 add_to_history = (m_command_source_depth == 0);
1650 add_to_history = (lazy_add_to_history == eLazyBoolYes);
1652 bool empty_command = false;
1653 bool comment_command = false;
1654 if (command_string.empty())
1655 empty_command = true;
1657 const char *k_space_characters = "\t\n\v\f\r ";
1659 size_t non_space = command_string.find_first_not_of(k_space_characters);
1660 // Check for empty line or comment line (lines whose first non-space
1661 // character is the comment character for this interpreter)
1662 if (non_space == std::string::npos)
1663 empty_command = true;
1664 else if (command_string[non_space] == m_comment_char)
1665 comment_command = true;
1666 else if (command_string[non_space] == CommandHistory::g_repeat_char) {
1667 llvm::StringRef search_str(command_string);
1668 search_str = search_str.drop_front(non_space);
1669 if (auto hist_str = m_command_history.FindString(search_str)) {
1670 add_to_history = false;
1671 command_string = *hist_str;
1672 original_command_string = *hist_str;
1674 result.AppendErrorWithFormat("Could not find entry: %s in history",
1675 command_string.c_str());
1676 result.SetStatus(eReturnStatusFailed);
1682 if (empty_command) {
1683 if (repeat_on_empty_command) {
1684 if (m_command_history.IsEmpty()) {
1685 result.AppendError("empty command");
1686 result.SetStatus(eReturnStatusFailed);
1689 command_line = m_repeat_command.c_str();
1690 command_string = command_line;
1691 original_command_string = command_line;
1692 if (m_repeat_command.empty()) {
1693 result.AppendErrorWithFormat("No auto repeat.\n");
1694 result.SetStatus(eReturnStatusFailed);
1698 add_to_history = false;
1700 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1703 } else if (comment_command) {
1704 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1708 Status error(PreprocessCommand(command_string));
1711 result.AppendError(error.AsCString());
1712 result.SetStatus(eReturnStatusFailed);
1718 // Before we do ANY kind of argument processing, we need to figure out what
1719 // the real/final command object is for the specified command. This gets
1720 // complicated by the fact that the user could have specified an alias, and,
1721 // in translating the alias, there may also be command options and/or even
1722 // data (including raw text strings) that need to be found and inserted into
1723 // the command line as part of the translation. So this first step is plain
1724 // look-up and replacement, resulting in:
1725 // 1. the command object whose Execute method will actually be called
1726 // 2. a revised command string, with all substitutions and replacements
1728 // From 1 above, we can determine whether the Execute function wants raw
1731 CommandObject *cmd_obj = ResolveCommandImpl(command_string, result);
1733 // Although the user may have abbreviated the command, the command_string now
1734 // has the command expanded to the full name. For example, if the input was
1735 // "br s -n main", command_string is now "breakpoint set -n main".
1737 llvm::StringRef command_name = cmd_obj ? cmd_obj->GetCommandName() : "<not found>";
1738 log->Printf("HandleCommand, cmd_obj : '%s'", command_name.str().c_str());
1739 log->Printf("HandleCommand, (revised) command_string: '%s'",
1740 command_string.c_str());
1741 const bool wants_raw_input =
1742 (cmd_obj != nullptr) ? cmd_obj->WantsRawCommandString() : false;
1743 log->Printf("HandleCommand, wants_raw_input:'%s'",
1744 wants_raw_input ? "True" : "False");
1748 // Take care of things like setting up the history command & calling the
1749 // appropriate Execute method on the CommandObject, with the appropriate
1752 if (cmd_obj != nullptr) {
1753 if (add_to_history) {
1754 Args command_args(command_string);
1755 const char *repeat_command = cmd_obj->GetRepeatCommand(command_args, 0);
1756 if (repeat_command != nullptr)
1757 m_repeat_command.assign(repeat_command);
1759 m_repeat_command.assign(original_command_string);
1761 m_command_history.AppendString(original_command_string);
1764 std::string remainder;
1765 const std::size_t actual_cmd_name_len = cmd_obj->GetCommandName().size();
1766 if (actual_cmd_name_len < command_string.length())
1767 remainder = command_string.substr(actual_cmd_name_len);
1769 // Remove any initial spaces
1770 size_t pos = remainder.find_first_not_of(k_white_space);
1771 if (pos != 0 && pos != std::string::npos)
1772 remainder.erase(0, pos);
1776 "HandleCommand, command line after removing command name(s): '%s'",
1779 cmd_obj->Execute(remainder.c_str(), result);
1783 log->Printf("HandleCommand, command %s",
1784 (result.Succeeded() ? "succeeded" : "did not succeed"));
1786 return result.Succeeded();
1789 int CommandInterpreter::HandleCompletionMatches(CompletionRequest &request) {
1790 int num_command_matches = 0;
1791 bool look_for_subcommand = false;
1793 // For any of the command completions a unique match will be a complete word.
1794 request.SetWordComplete(true);
1796 if (request.GetCursorIndex() == -1) {
1797 // We got nothing on the command line, so return the list of commands
1798 bool include_aliases = true;
1799 StringList new_matches, descriptions;
1800 num_command_matches = GetCommandNamesMatchingPartialString(
1801 "", include_aliases, new_matches, descriptions);
1802 request.AddCompletions(new_matches, descriptions);
1803 } else if (request.GetCursorIndex() == 0) {
1804 // The cursor is in the first argument, so just do a lookup in the
1806 StringList new_matches, new_descriptions;
1807 CommandObject *cmd_obj =
1808 GetCommandObject(request.GetParsedLine().GetArgumentAtIndex(0),
1809 &new_matches, &new_descriptions);
1811 if (num_command_matches == 1 && cmd_obj && cmd_obj->IsMultiwordObject() &&
1812 new_matches.GetStringAtIndex(0) != nullptr &&
1813 strcmp(request.GetParsedLine().GetArgumentAtIndex(0),
1814 new_matches.GetStringAtIndex(0)) == 0) {
1815 if (request.GetParsedLine().GetArgumentCount() == 1) {
1816 request.SetWordComplete(true);
1818 look_for_subcommand = true;
1819 num_command_matches = 0;
1820 new_matches.DeleteStringAtIndex(0);
1821 new_descriptions.DeleteStringAtIndex(0);
1822 request.GetParsedLine().AppendArgument(llvm::StringRef());
1823 request.SetCursorIndex(request.GetCursorIndex() + 1);
1824 request.SetCursorCharPosition(0);
1827 request.AddCompletions(new_matches, new_descriptions);
1828 num_command_matches = request.GetNumberOfMatches();
1831 if (request.GetCursorIndex() > 0 || look_for_subcommand) {
1832 // We are completing further on into a commands arguments, so find the
1833 // command and tell it to complete the command. First see if there is a
1834 // matching initial command:
1835 CommandObject *command_object =
1836 GetCommandObject(request.GetParsedLine().GetArgumentAtIndex(0));
1837 if (command_object == nullptr) {
1840 request.GetParsedLine().Shift();
1841 request.SetCursorIndex(request.GetCursorIndex() - 1);
1842 num_command_matches = command_object->HandleCompletion(request);
1846 return num_command_matches;
1849 int CommandInterpreter::HandleCompletion(
1850 const char *current_line, const char *cursor, const char *last_char,
1851 int match_start_point, int max_return_elements, StringList &matches,
1852 StringList &descriptions) {
1854 llvm::StringRef command_line(current_line, last_char - current_line);
1855 CompletionResult result;
1856 CompletionRequest request(command_line, cursor - current_line,
1857 match_start_point, max_return_elements, result);
1858 // Don't complete comments, and if the line we are completing is just the
1859 // history repeat character, substitute the appropriate history line.
1860 const char *first_arg = request.GetParsedLine().GetArgumentAtIndex(0);
1862 if (first_arg[0] == m_comment_char)
1864 else if (first_arg[0] == CommandHistory::g_repeat_char) {
1865 if (auto hist_str = m_command_history.FindString(first_arg)) {
1866 matches.InsertStringAtIndex(0, *hist_str);
1867 descriptions.InsertStringAtIndex(0, "Previous command history event");
1874 // Only max_return_elements == -1 is supported at present:
1875 lldbassert(max_return_elements == -1);
1877 int num_command_matches = HandleCompletionMatches(request);
1878 result.GetMatches(matches);
1879 result.GetDescriptions(descriptions);
1881 if (num_command_matches <= 0)
1882 return num_command_matches;
1884 if (request.GetParsedLine().GetArgumentCount() == 0) {
1885 // If we got an empty string, insert nothing.
1886 matches.InsertStringAtIndex(0, "");
1887 descriptions.InsertStringAtIndex(0, "");
1889 // Now figure out if there is a common substring, and if so put that in
1890 // element 0, otherwise put an empty string in element 0.
1891 std::string command_partial_str = request.GetCursorArgumentPrefix().str();
1893 std::string common_prefix;
1894 matches.LongestCommonPrefix(common_prefix);
1895 const size_t partial_name_len = command_partial_str.size();
1896 common_prefix.erase(0, partial_name_len);
1898 // If we matched a unique single command, add a space... Only do this if
1899 // the completer told us this was a complete word, however...
1900 if (num_command_matches == 1 && request.GetWordComplete()) {
1901 char quote_char = request.GetParsedLine()[request.GetCursorIndex()].quote;
1903 Args::EscapeLLDBCommandArgument(common_prefix, quote_char);
1904 if (quote_char != '\0')
1905 common_prefix.push_back(quote_char);
1906 common_prefix.push_back(' ');
1908 matches.InsertStringAtIndex(0, common_prefix.c_str());
1909 descriptions.InsertStringAtIndex(0, "");
1911 return num_command_matches;
1914 CommandInterpreter::~CommandInterpreter() {}
1916 void CommandInterpreter::UpdatePrompt(llvm::StringRef new_prompt) {
1917 EventSP prompt_change_event_sp(
1918 new Event(eBroadcastBitResetPrompt, new EventDataBytes(new_prompt)));
1920 BroadcastEvent(prompt_change_event_sp);
1921 if (m_command_io_handler_sp)
1922 m_command_io_handler_sp->SetPrompt(new_prompt);
1925 bool CommandInterpreter::Confirm(llvm::StringRef message, bool default_answer) {
1926 // Check AutoConfirm first:
1927 if (m_debugger.GetAutoConfirm())
1928 return default_answer;
1930 IOHandlerConfirm *confirm =
1931 new IOHandlerConfirm(m_debugger, message, default_answer);
1932 IOHandlerSP io_handler_sp(confirm);
1933 m_debugger.RunIOHandler(io_handler_sp);
1934 return confirm->GetResponse();
1937 const CommandAlias *
1938 CommandInterpreter::GetAlias(llvm::StringRef alias_name) const {
1939 OptionArgVectorSP ret_val;
1941 auto pos = m_alias_dict.find(alias_name);
1942 if (pos != m_alias_dict.end())
1943 return (CommandAlias *)pos->second.get();
1948 bool CommandInterpreter::HasCommands() const { return (!m_command_dict.empty()); }
1950 bool CommandInterpreter::HasAliases() const { return (!m_alias_dict.empty()); }
1952 bool CommandInterpreter::HasUserCommands() const { return (!m_user_dict.empty()); }
1954 bool CommandInterpreter::HasAliasOptions() const { return HasAliases(); }
1956 void CommandInterpreter::BuildAliasCommandArgs(CommandObject *alias_cmd_obj,
1957 const char *alias_name,
1959 std::string &raw_input_string,
1960 CommandReturnObject &result) {
1961 OptionArgVectorSP option_arg_vector_sp =
1962 GetAlias(alias_name)->GetOptionArguments();
1964 bool wants_raw_input = alias_cmd_obj->WantsRawCommandString();
1966 // Make sure that the alias name is the 0th element in cmd_args
1967 std::string alias_name_str = alias_name;
1968 if (alias_name_str != cmd_args.GetArgumentAtIndex(0))
1969 cmd_args.Unshift(alias_name_str);
1971 Args new_args(alias_cmd_obj->GetCommandName());
1972 if (new_args.GetArgumentCount() == 2)
1975 if (option_arg_vector_sp.get()) {
1976 if (wants_raw_input) {
1977 // We have a command that both has command options and takes raw input.
1978 // Make *sure* it has a " -- " in the right place in the
1979 // raw_input_string.
1980 size_t pos = raw_input_string.find(" -- ");
1981 if (pos == std::string::npos) {
1982 // None found; assume it goes at the beginning of the raw input string
1983 raw_input_string.insert(0, " -- ");
1987 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
1988 const size_t old_size = cmd_args.GetArgumentCount();
1989 std::vector<bool> used(old_size + 1, false);
1996 for (const auto &option_entry : *option_arg_vector) {
1997 std::tie(option, value_type, value) = option_entry;
1998 if (option == "<argument>") {
1999 if (!wants_raw_input || (value != "--")) {
2000 // Since we inserted this above, make sure we don't insert it twice
2001 new_args.AppendArgument(value);
2006 if (value_type != OptionParser::eOptionalArgument)
2007 new_args.AppendArgument(option);
2009 if (value == "<no-argument>")
2012 int index = GetOptionArgumentPosition(value.c_str());
2014 // value was NOT a positional argument; must be a real value
2015 if (value_type != OptionParser::eOptionalArgument)
2016 new_args.AppendArgument(value);
2019 ::snprintf(buffer, sizeof(buffer), "%s%s", option.c_str(),
2021 new_args.AppendArgument(llvm::StringRef(buffer));
2024 } else if (static_cast<size_t>(index) >= cmd_args.GetArgumentCount()) {
2025 result.AppendErrorWithFormat("Not enough arguments provided; you "
2026 "need at least %d arguments to use "
2029 result.SetStatus(eReturnStatusFailed);
2032 // Find and remove cmd_args.GetArgumentAtIndex(i) from raw_input_string
2034 raw_input_string.find(cmd_args.GetArgumentAtIndex(index));
2035 if (strpos != std::string::npos) {
2036 raw_input_string = raw_input_string.erase(
2037 strpos, strlen(cmd_args.GetArgumentAtIndex(index)));
2040 if (value_type != OptionParser::eOptionalArgument)
2041 new_args.AppendArgument(cmd_args.GetArgumentAtIndex(index));
2044 ::snprintf(buffer, sizeof(buffer), "%s%s", option.c_str(),
2045 cmd_args.GetArgumentAtIndex(index));
2046 new_args.AppendArgument(buffer);
2052 for (auto entry : llvm::enumerate(cmd_args.entries())) {
2053 if (!used[entry.index()] && !wants_raw_input)
2054 new_args.AppendArgument(entry.value().ref);
2058 cmd_args.SetArguments(new_args.GetArgumentCount(),
2059 new_args.GetConstArgumentVector());
2061 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2062 // This alias was not created with any options; nothing further needs to be
2063 // done, unless it is a command that wants raw input, in which case we need
2064 // to clear the rest of the data from cmd_args, since its in the raw input
2066 if (wants_raw_input) {
2068 cmd_args.SetArguments(new_args.GetArgumentCount(),
2069 new_args.GetConstArgumentVector());
2074 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2078 int CommandInterpreter::GetOptionArgumentPosition(const char *in_string) {
2079 int position = 0; // Any string that isn't an argument position, i.e. '%'
2080 // followed by an integer, gets a position
2083 const char *cptr = in_string;
2085 // Does it start with '%'
2086 if (cptr[0] == '%') {
2089 // Is the rest of it entirely digits?
2090 if (isdigit(cptr[0])) {
2091 const char *start = cptr;
2092 while (isdigit(cptr[0]))
2095 // We've gotten to the end of the digits; are we at the end of the
2097 if (cptr[0] == '\0')
2098 position = atoi(start);
2105 static void GetHomeInitFile(llvm::SmallVectorImpl<char> &init_file,
2106 llvm::StringRef suffix = {}) {
2107 std::string init_file_name = ".lldbinit";
2108 if (!suffix.empty()) {
2109 init_file_name.append("-");
2110 init_file_name.append(suffix.str());
2113 llvm::sys::path::home_directory(init_file);
2114 llvm::sys::path::append(init_file, init_file_name);
2116 FileSystem::Instance().Resolve(init_file);
2119 static void GetCwdInitFile(llvm::SmallVectorImpl<char> &init_file) {
2120 llvm::StringRef s = ".lldbinit";
2121 init_file.assign(s.begin(), s.end());
2122 FileSystem::Instance().Resolve(init_file);
2125 static LoadCWDlldbinitFile ShouldLoadCwdInitFile() {
2126 lldb::TargetPropertiesSP properties = Target::GetGlobalProperties();
2128 return eLoadCWDlldbinitFalse;
2129 return properties->GetLoadCWDlldbinitFile();
2132 void CommandInterpreter::SourceInitFile(FileSpec file,
2133 CommandReturnObject &result) {
2134 assert(!m_skip_lldbinit_files);
2136 if (!FileSystem::Instance().Exists(file)) {
2137 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2141 // Use HandleCommand to 'source' the given file; this will do the actual
2142 // broadcasting of the commands back to any appropriate listener (see
2143 // CommandObjectSource::Execute for more details).
2144 const bool saved_batch = SetBatchCommandMode(true);
2145 ExecutionContext *ctx = nullptr;
2146 CommandInterpreterRunOptions options;
2147 options.SetSilent(true);
2148 options.SetPrintErrors(true);
2149 options.SetStopOnError(false);
2150 options.SetStopOnContinue(true);
2151 HandleCommandsFromFile(file, ctx, options, result);
2152 SetBatchCommandMode(saved_batch);
2155 void CommandInterpreter::SourceInitFileCwd(CommandReturnObject &result) {
2156 if (m_skip_lldbinit_files) {
2157 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2161 llvm::SmallString<128> init_file;
2162 GetCwdInitFile(init_file);
2163 if (!FileSystem::Instance().Exists(init_file)) {
2164 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2168 LoadCWDlldbinitFile should_load = ShouldLoadCwdInitFile();
2170 switch (should_load) {
2171 case eLoadCWDlldbinitFalse:
2172 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2174 case eLoadCWDlldbinitTrue:
2175 SourceInitFile(FileSpec(init_file.str()), result);
2177 case eLoadCWDlldbinitWarn: {
2178 llvm::SmallString<128> home_init_file;
2179 GetHomeInitFile(home_init_file);
2180 if (llvm::sys::path::parent_path(init_file) ==
2181 llvm::sys::path::parent_path(home_init_file)) {
2182 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2184 result.AppendErrorWithFormat(InitFileWarning);
2185 result.SetStatus(eReturnStatusFailed);
2191 /// We will first see if there is an application specific ".lldbinit" file
2192 /// whose name is "~/.lldbinit" followed by a "-" and the name of the program.
2193 /// If this file doesn't exist, we fall back to just the "~/.lldbinit" file.
2194 void CommandInterpreter::SourceInitFileHome(CommandReturnObject &result) {
2195 if (m_skip_lldbinit_files) {
2196 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2200 llvm::SmallString<128> init_file;
2201 GetHomeInitFile(init_file);
2203 if (!m_skip_app_init_files) {
2204 llvm::StringRef program_name =
2205 HostInfo::GetProgramFileSpec().GetFilename().GetStringRef();
2206 llvm::SmallString<128> program_init_file;
2207 GetHomeInitFile(program_init_file, program_name);
2208 if (FileSystem::Instance().Exists(program_init_file))
2209 init_file = program_init_file;
2212 SourceInitFile(FileSpec(init_file.str()), result);
2215 const char *CommandInterpreter::GetCommandPrefix() {
2216 const char *prefix = GetDebugger().GetIOHandlerCommandPrefix();
2217 return prefix == nullptr ? "" : prefix;
2220 PlatformSP CommandInterpreter::GetPlatform(bool prefer_target_platform) {
2221 PlatformSP platform_sp;
2222 if (prefer_target_platform) {
2223 ExecutionContext exe_ctx(GetExecutionContext());
2224 Target *target = exe_ctx.GetTargetPtr();
2226 platform_sp = target->GetPlatform();
2230 platform_sp = m_debugger.GetPlatformList().GetSelectedPlatform();
2234 void CommandInterpreter::HandleCommands(const StringList &commands,
2235 ExecutionContext *override_context,
2236 CommandInterpreterRunOptions &options,
2237 CommandReturnObject &result) {
2238 size_t num_lines = commands.GetSize();
2240 // If we are going to continue past a "continue" then we need to run the
2241 // commands synchronously. Make sure you reset this value anywhere you return
2242 // from the function.
2244 bool old_async_execution = m_debugger.GetAsyncExecution();
2246 // If we've been given an execution context, set it at the start, but don't
2247 // keep resetting it or we will cause series of commands that change the
2248 // context, then do an operation that relies on that context to fail.
2250 if (override_context != nullptr)
2251 UpdateExecutionContext(override_context);
2253 if (!options.GetStopOnContinue()) {
2254 m_debugger.SetAsyncExecution(false);
2257 for (size_t idx = 0; idx < num_lines && !WasInterrupted(); idx++) {
2258 const char *cmd = commands.GetStringAtIndex(idx);
2262 if (options.GetEchoCommands()) {
2263 // TODO: Add Stream support.
2264 result.AppendMessageWithFormat("%s %s\n",
2265 m_debugger.GetPrompt().str().c_str(), cmd);
2268 CommandReturnObject tmp_result;
2269 // If override_context is not NULL, pass no_context_switching = true for
2270 // HandleCommand() since we updated our context already.
2272 // We might call into a regex or alias command, in which case the
2273 // add_to_history will get lost. This m_command_source_depth dingus is the
2274 // way we turn off adding to the history in that case, so set it up here.
2275 if (!options.GetAddToHistory())
2276 m_command_source_depth++;
2278 HandleCommand(cmd, options.m_add_to_history, tmp_result,
2279 nullptr, /* override_context */
2280 true, /* repeat_on_empty_command */
2281 override_context != nullptr /* no_context_switching */);
2282 if (!options.GetAddToHistory())
2283 m_command_source_depth--;
2285 if (options.GetPrintResults()) {
2286 if (tmp_result.Succeeded())
2287 result.AppendMessage(tmp_result.GetOutputData());
2290 if (!success || !tmp_result.Succeeded()) {
2291 llvm::StringRef error_msg = tmp_result.GetErrorData();
2292 if (error_msg.empty())
2293 error_msg = "<unknown error>.\n";
2294 if (options.GetStopOnError()) {
2295 result.AppendErrorWithFormat(
2296 "Aborting reading of commands after command #%" PRIu64
2297 ": '%s' failed with %s",
2298 (uint64_t)idx, cmd, error_msg.str().c_str());
2299 result.SetStatus(eReturnStatusFailed);
2300 m_debugger.SetAsyncExecution(old_async_execution);
2302 } else if (options.GetPrintResults()) {
2303 result.AppendMessageWithFormat(
2304 "Command #%" PRIu64 " '%s' failed with %s", (uint64_t)idx + 1, cmd,
2305 error_msg.str().c_str());
2309 if (result.GetImmediateOutputStream())
2310 result.GetImmediateOutputStream()->Flush();
2312 if (result.GetImmediateErrorStream())
2313 result.GetImmediateErrorStream()->Flush();
2315 // N.B. Can't depend on DidChangeProcessState, because the state coming
2316 // into the command execution could be running (for instance in Breakpoint
2317 // Commands. So we check the return value to see if it is has running in
2319 if ((tmp_result.GetStatus() == eReturnStatusSuccessContinuingNoResult) ||
2320 (tmp_result.GetStatus() == eReturnStatusSuccessContinuingResult)) {
2321 if (options.GetStopOnContinue()) {
2322 // If we caused the target to proceed, and we're going to stop in that
2323 // case, set the status in our real result before returning. This is
2324 // an error if the continue was not the last command in the set of
2325 // commands to be run.
2326 if (idx != num_lines - 1)
2327 result.AppendErrorWithFormat(
2328 "Aborting reading of commands after command #%" PRIu64
2329 ": '%s' continued the target.\n",
2330 (uint64_t)idx + 1, cmd);
2332 result.AppendMessageWithFormat("Command #%" PRIu64
2333 " '%s' continued the target.\n",
2334 (uint64_t)idx + 1, cmd);
2336 result.SetStatus(tmp_result.GetStatus());
2337 m_debugger.SetAsyncExecution(old_async_execution);
2343 // Also check for "stop on crash here:
2344 bool should_stop = false;
2345 if (tmp_result.GetDidChangeProcessState() && options.GetStopOnCrash()) {
2346 TargetSP target_sp(m_debugger.GetTargetList().GetSelectedTarget());
2348 ProcessSP process_sp(target_sp->GetProcessSP());
2350 for (ThreadSP thread_sp : process_sp->GetThreadList().Threads()) {
2351 StopReason reason = thread_sp->GetStopReason();
2352 if (reason == eStopReasonSignal || reason == eStopReasonException ||
2353 reason == eStopReasonInstrumentation) {
2361 if (idx != num_lines - 1)
2362 result.AppendErrorWithFormat(
2363 "Aborting reading of commands after command #%" PRIu64
2364 ": '%s' stopped with a signal or exception.\n",
2365 (uint64_t)idx + 1, cmd);
2367 result.AppendMessageWithFormat(
2368 "Command #%" PRIu64 " '%s' stopped with a signal or exception.\n",
2369 (uint64_t)idx + 1, cmd);
2371 result.SetStatus(tmp_result.GetStatus());
2372 m_debugger.SetAsyncExecution(old_async_execution);
2379 result.SetStatus(eReturnStatusSuccessFinishResult);
2380 m_debugger.SetAsyncExecution(old_async_execution);
2385 // Make flags that we can pass into the IOHandler so our delegates can do the
2388 eHandleCommandFlagStopOnContinue = (1u << 0),
2389 eHandleCommandFlagStopOnError = (1u << 1),
2390 eHandleCommandFlagEchoCommand = (1u << 2),
2391 eHandleCommandFlagEchoCommentCommand = (1u << 3),
2392 eHandleCommandFlagPrintResult = (1u << 4),
2393 eHandleCommandFlagPrintErrors = (1u << 5),
2394 eHandleCommandFlagStopOnCrash = (1u << 6)
2397 void CommandInterpreter::HandleCommandsFromFile(
2398 FileSpec &cmd_file, ExecutionContext *context,
2399 CommandInterpreterRunOptions &options, CommandReturnObject &result) {
2400 if (!FileSystem::Instance().Exists(cmd_file)) {
2401 result.AppendErrorWithFormat(
2402 "Error reading commands from file %s - file not found.\n",
2403 cmd_file.GetFilename().AsCString("<Unknown>"));
2404 result.SetStatus(eReturnStatusFailed);
2408 StreamFileSP input_file_sp(new StreamFile());
2409 std::string cmd_file_path = cmd_file.GetPath();
2410 Status error = FileSystem::Instance().Open(input_file_sp->GetFile(), cmd_file,
2411 File::eOpenOptionRead);
2414 result.AppendErrorWithFormat(
2415 "error: an error occurred read file '%s': %s\n", cmd_file_path.c_str(),
2417 result.SetStatus(eReturnStatusFailed);
2421 Debugger &debugger = GetDebugger();
2425 if (options.m_stop_on_continue == eLazyBoolCalculate) {
2426 if (m_command_source_flags.empty()) {
2427 // Stop on continue by default
2428 flags |= eHandleCommandFlagStopOnContinue;
2429 } else if (m_command_source_flags.back() &
2430 eHandleCommandFlagStopOnContinue) {
2431 flags |= eHandleCommandFlagStopOnContinue;
2433 } else if (options.m_stop_on_continue == eLazyBoolYes) {
2434 flags |= eHandleCommandFlagStopOnContinue;
2437 if (options.m_stop_on_error == eLazyBoolCalculate) {
2438 if (m_command_source_flags.empty()) {
2439 if (GetStopCmdSourceOnError())
2440 flags |= eHandleCommandFlagStopOnError;
2441 } else if (m_command_source_flags.back() & eHandleCommandFlagStopOnError) {
2442 flags |= eHandleCommandFlagStopOnError;
2444 } else if (options.m_stop_on_error == eLazyBoolYes) {
2445 flags |= eHandleCommandFlagStopOnError;
2448 // stop-on-crash can only be set, if it is present in all levels of
2449 // pushed flag sets.
2450 if (options.GetStopOnCrash()) {
2451 if (m_command_source_flags.empty()) {
2452 flags |= eHandleCommandFlagStopOnCrash;
2453 } else if (m_command_source_flags.back() & eHandleCommandFlagStopOnCrash) {
2454 flags |= eHandleCommandFlagStopOnCrash;
2458 if (options.m_echo_commands == eLazyBoolCalculate) {
2459 if (m_command_source_flags.empty()) {
2460 // Echo command by default
2461 flags |= eHandleCommandFlagEchoCommand;
2462 } else if (m_command_source_flags.back() & eHandleCommandFlagEchoCommand) {
2463 flags |= eHandleCommandFlagEchoCommand;
2465 } else if (options.m_echo_commands == eLazyBoolYes) {
2466 flags |= eHandleCommandFlagEchoCommand;
2469 // We will only ever ask for this flag, if we echo commands in general.
2470 if (options.m_echo_comment_commands == eLazyBoolCalculate) {
2471 if (m_command_source_flags.empty()) {
2472 // Echo comments by default
2473 flags |= eHandleCommandFlagEchoCommentCommand;
2474 } else if (m_command_source_flags.back() &
2475 eHandleCommandFlagEchoCommentCommand) {
2476 flags |= eHandleCommandFlagEchoCommentCommand;
2478 } else if (options.m_echo_comment_commands == eLazyBoolYes) {
2479 flags |= eHandleCommandFlagEchoCommentCommand;
2482 if (options.m_print_results == eLazyBoolCalculate) {
2483 if (m_command_source_flags.empty()) {
2484 // Print output by default
2485 flags |= eHandleCommandFlagPrintResult;
2486 } else if (m_command_source_flags.back() & eHandleCommandFlagPrintResult) {
2487 flags |= eHandleCommandFlagPrintResult;
2489 } else if (options.m_print_results == eLazyBoolYes) {
2490 flags |= eHandleCommandFlagPrintResult;
2493 if (options.m_print_errors == eLazyBoolCalculate) {
2494 if (m_command_source_flags.empty()) {
2495 // Print output by default
2496 flags |= eHandleCommandFlagPrintErrors;
2497 } else if (m_command_source_flags.back() & eHandleCommandFlagPrintErrors) {
2498 flags |= eHandleCommandFlagPrintErrors;
2500 } else if (options.m_print_errors == eLazyBoolYes) {
2501 flags |= eHandleCommandFlagPrintErrors;
2504 if (flags & eHandleCommandFlagPrintResult) {
2505 debugger.GetOutputFile()->Printf("Executing commands in '%s'.\n",
2506 cmd_file_path.c_str());
2509 // Used for inheriting the right settings when "command source" might
2510 // have nested "command source" commands
2511 lldb::StreamFileSP empty_stream_sp;
2512 m_command_source_flags.push_back(flags);
2513 IOHandlerSP io_handler_sp(new IOHandlerEditline(
2514 debugger, IOHandler::Type::CommandInterpreter, input_file_sp,
2515 empty_stream_sp, // Pass in an empty stream so we inherit the top
2516 // input reader output stream
2517 empty_stream_sp, // Pass in an empty stream so we inherit the top
2518 // input reader error stream
2520 nullptr, // Pass in NULL for "editline_name" so no history is saved,
2522 debugger.GetPrompt(), llvm::StringRef(),
2523 false, // Not multi-line
2524 debugger.GetUseColor(), 0, *this, nullptr));
2525 const bool old_async_execution = debugger.GetAsyncExecution();
2527 // Set synchronous execution if we are not stopping on continue
2528 if ((flags & eHandleCommandFlagStopOnContinue) == 0)
2529 debugger.SetAsyncExecution(false);
2531 m_command_source_depth++;
2533 debugger.RunIOHandler(io_handler_sp);
2534 if (!m_command_source_flags.empty())
2535 m_command_source_flags.pop_back();
2536 m_command_source_depth--;
2537 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2538 debugger.SetAsyncExecution(old_async_execution);
2541 bool CommandInterpreter::GetSynchronous() { return m_synchronous_execution; }
2543 void CommandInterpreter::SetSynchronous(bool value) {
2544 m_synchronous_execution = value;
2547 void CommandInterpreter::OutputFormattedHelpText(Stream &strm,
2548 llvm::StringRef prefix,
2549 llvm::StringRef help_text) {
2550 const uint32_t max_columns = m_debugger.GetTerminalWidth();
2552 size_t line_width_max = max_columns - prefix.size();
2553 if (line_width_max < 16)
2554 line_width_max = help_text.size() + prefix.size();
2556 strm.IndentMore(prefix.size());
2557 bool prefixed_yet = false;
2558 while (!help_text.empty()) {
2559 // Prefix the first line, indent subsequent lines to line up
2560 if (!prefixed_yet) {
2562 prefixed_yet = true;
2566 // Never print more than the maximum on one line.
2567 llvm::StringRef this_line = help_text.substr(0, line_width_max);
2569 // Always break on an explicit newline.
2570 std::size_t first_newline = this_line.find_first_of("\n");
2572 // Don't break on space/tab unless the text is too long to fit on one line.
2573 std::size_t last_space = llvm::StringRef::npos;
2574 if (this_line.size() != help_text.size())
2575 last_space = this_line.find_last_of(" \t");
2577 // Break at whichever condition triggered first.
2578 this_line = this_line.substr(0, std::min(first_newline, last_space));
2579 strm.PutCString(this_line);
2582 // Remove whitespace / newlines after breaking.
2583 help_text = help_text.drop_front(this_line.size()).ltrim();
2585 strm.IndentLess(prefix.size());
2588 void CommandInterpreter::OutputFormattedHelpText(Stream &strm,
2589 llvm::StringRef word_text,
2590 llvm::StringRef separator,
2591 llvm::StringRef help_text,
2592 size_t max_word_len) {
2593 StreamString prefix_stream;
2594 prefix_stream.Printf(" %-*s %*s ", (int)max_word_len, word_text.data(),
2595 (int)separator.size(), separator.data());
2596 OutputFormattedHelpText(strm, prefix_stream.GetString(), help_text);
2599 void CommandInterpreter::OutputHelpText(Stream &strm, llvm::StringRef word_text,
2600 llvm::StringRef separator,
2601 llvm::StringRef help_text,
2602 uint32_t max_word_len) {
2603 int indent_size = max_word_len + separator.size() + 2;
2605 strm.IndentMore(indent_size);
2607 StreamString text_strm;
2608 text_strm.Printf("%-*s ", (int)max_word_len, word_text.data());
2609 text_strm << separator << " " << help_text;
2611 const uint32_t max_columns = m_debugger.GetTerminalWidth();
2613 llvm::StringRef text = text_strm.GetString();
2615 uint32_t chars_left = max_columns;
2617 auto nextWordLength = [](llvm::StringRef S) {
2618 size_t pos = S.find(' ');
2619 return pos == llvm::StringRef::npos ? S.size() : pos;
2622 while (!text.empty()) {
2623 if (text.front() == '\n' ||
2624 (text.front() == ' ' && nextWordLength(text.ltrim(' ')) > chars_left)) {
2627 chars_left = max_columns - indent_size;
2628 if (text.front() == '\n')
2629 text = text.drop_front();
2631 text = text.ltrim(' ');
2633 strm.PutChar(text.front());
2635 text = text.drop_front();
2640 strm.IndentLess(indent_size);
2643 void CommandInterpreter::FindCommandsForApropos(
2644 llvm::StringRef search_word, StringList &commands_found,
2645 StringList &commands_help, CommandObject::CommandMap &command_map) {
2646 CommandObject::CommandMap::const_iterator pos;
2648 for (pos = command_map.begin(); pos != command_map.end(); ++pos) {
2649 llvm::StringRef command_name = pos->first;
2650 CommandObject *cmd_obj = pos->second.get();
2652 const bool search_short_help = true;
2653 const bool search_long_help = false;
2654 const bool search_syntax = false;
2655 const bool search_options = false;
2656 if (command_name.contains_lower(search_word) ||
2657 cmd_obj->HelpTextContainsWord(search_word, search_short_help,
2658 search_long_help, search_syntax,
2660 commands_found.AppendString(cmd_obj->GetCommandName());
2661 commands_help.AppendString(cmd_obj->GetHelp());
2664 if (cmd_obj->IsMultiwordObject()) {
2665 CommandObjectMultiword *cmd_multiword = cmd_obj->GetAsMultiwordCommand();
2666 FindCommandsForApropos(search_word, commands_found, commands_help,
2667 cmd_multiword->GetSubcommandDictionary());
2672 void CommandInterpreter::FindCommandsForApropos(llvm::StringRef search_word,
2673 StringList &commands_found,
2674 StringList &commands_help,
2675 bool search_builtin_commands,
2676 bool search_user_commands,
2677 bool search_alias_commands) {
2678 CommandObject::CommandMap::const_iterator pos;
2680 if (search_builtin_commands)
2681 FindCommandsForApropos(search_word, commands_found, commands_help,
2684 if (search_user_commands)
2685 FindCommandsForApropos(search_word, commands_found, commands_help,
2688 if (search_alias_commands)
2689 FindCommandsForApropos(search_word, commands_found, commands_help,
2693 void CommandInterpreter::UpdateExecutionContext(
2694 ExecutionContext *override_context) {
2695 if (override_context != nullptr) {
2696 m_exe_ctx_ref = *override_context;
2698 const bool adopt_selected = true;
2699 m_exe_ctx_ref.SetTargetPtr(m_debugger.GetSelectedTarget().get(),
2704 size_t CommandInterpreter::GetProcessOutput() {
2705 // The process has stuff waiting for stderr; get it and write it out to the
2706 // appropriate place.
2707 char stdio_buffer[1024];
2709 size_t total_bytes = 0;
2711 TargetSP target_sp(m_debugger.GetTargetList().GetSelectedTarget());
2713 ProcessSP process_sp(target_sp->GetProcessSP());
2715 while ((len = process_sp->GetSTDOUT(stdio_buffer, sizeof(stdio_buffer),
2717 size_t bytes_written = len;
2718 m_debugger.GetOutputFile()->Write(stdio_buffer, bytes_written);
2721 while ((len = process_sp->GetSTDERR(stdio_buffer, sizeof(stdio_buffer),
2723 size_t bytes_written = len;
2724 m_debugger.GetErrorFile()->Write(stdio_buffer, bytes_written);
2732 void CommandInterpreter::StartHandlingCommand() {
2733 auto idle_state = CommandHandlingState::eIdle;
2734 if (m_command_state.compare_exchange_strong(
2735 idle_state, CommandHandlingState::eInProgress))
2736 lldbassert(m_iohandler_nesting_level == 0);
2738 lldbassert(m_iohandler_nesting_level > 0);
2739 ++m_iohandler_nesting_level;
2742 void CommandInterpreter::FinishHandlingCommand() {
2743 lldbassert(m_iohandler_nesting_level > 0);
2744 if (--m_iohandler_nesting_level == 0) {
2745 auto prev_state = m_command_state.exchange(CommandHandlingState::eIdle);
2746 lldbassert(prev_state != CommandHandlingState::eIdle);
2750 bool CommandInterpreter::InterruptCommand() {
2751 auto in_progress = CommandHandlingState::eInProgress;
2752 return m_command_state.compare_exchange_strong(
2753 in_progress, CommandHandlingState::eInterrupted);
2756 bool CommandInterpreter::WasInterrupted() const {
2757 bool was_interrupted =
2758 (m_command_state == CommandHandlingState::eInterrupted);
2759 lldbassert(!was_interrupted || m_iohandler_nesting_level > 0);
2760 return was_interrupted;
2763 void CommandInterpreter::PrintCommandOutput(Stream &stream,
2764 llvm::StringRef str) {
2765 // Split the output into lines and poll for interrupt requests
2766 const char *data = str.data();
2767 size_t size = str.size();
2768 while (size > 0 && !WasInterrupted()) {
2769 size_t chunk_size = 0;
2770 for (; chunk_size < size; ++chunk_size) {
2771 lldbassert(data[chunk_size] != '\0');
2772 if (data[chunk_size] == '\n') {
2777 chunk_size = stream.Write(data, chunk_size);
2778 lldbassert(size >= chunk_size);
2783 stream.Printf("\n... Interrupted.\n");
2787 bool CommandInterpreter::EchoCommandNonInteractive(
2788 llvm::StringRef line, const Flags &io_handler_flags) const {
2789 if (!io_handler_flags.Test(eHandleCommandFlagEchoCommand))
2792 llvm::StringRef command = line.trim();
2793 if (command.empty())
2796 if (command.front() == m_comment_char)
2797 return io_handler_flags.Test(eHandleCommandFlagEchoCommentCommand);
2802 void CommandInterpreter::IOHandlerInputComplete(IOHandler &io_handler,
2803 std::string &line) {
2804 // If we were interrupted, bail out...
2805 if (WasInterrupted())
2808 const bool is_interactive = io_handler.GetIsInteractive();
2809 if (!is_interactive) {
2810 // When we are not interactive, don't execute blank lines. This will happen
2811 // sourcing a commands file. We don't want blank lines to repeat the
2812 // previous command and cause any errors to occur (like redefining an
2813 // alias, get an error and stop parsing the commands file).
2817 // When using a non-interactive file handle (like when sourcing commands
2818 // from a file) we need to echo the command out so we don't just see the
2819 // command output and no command...
2820 if (EchoCommandNonInteractive(line, io_handler.GetFlags()))
2821 io_handler.GetOutputStreamFile()->Printf("%s%s\n", io_handler.GetPrompt(),
2825 StartHandlingCommand();
2827 lldb_private::CommandReturnObject result;
2828 HandleCommand(line.c_str(), eLazyBoolCalculate, result);
2830 // Now emit the command output text from the command we just executed
2831 if ((result.Succeeded() &&
2832 io_handler.GetFlags().Test(eHandleCommandFlagPrintResult)) ||
2833 io_handler.GetFlags().Test(eHandleCommandFlagPrintErrors)) {
2834 // Display any STDOUT/STDERR _prior_ to emitting the command result text
2837 if (!result.GetImmediateOutputStream()) {
2838 llvm::StringRef output = result.GetOutputData();
2839 PrintCommandOutput(*io_handler.GetOutputStreamFile(), output);
2842 // Now emit the command error text from the command we just executed
2843 if (!result.GetImmediateErrorStream()) {
2844 llvm::StringRef error = result.GetErrorData();
2845 PrintCommandOutput(*io_handler.GetErrorStreamFile(), error);
2849 FinishHandlingCommand();
2851 switch (result.GetStatus()) {
2852 case eReturnStatusInvalid:
2853 case eReturnStatusSuccessFinishNoResult:
2854 case eReturnStatusSuccessFinishResult:
2855 case eReturnStatusStarted:
2858 case eReturnStatusSuccessContinuingNoResult:
2859 case eReturnStatusSuccessContinuingResult:
2860 if (io_handler.GetFlags().Test(eHandleCommandFlagStopOnContinue))
2861 io_handler.SetIsDone(true);
2864 case eReturnStatusFailed:
2866 if (io_handler.GetFlags().Test(eHandleCommandFlagStopOnError))
2867 io_handler.SetIsDone(true);
2870 case eReturnStatusQuit:
2871 m_quit_requested = true;
2872 io_handler.SetIsDone(true);
2876 // Finally, if we're going to stop on crash, check that here:
2877 if (!m_quit_requested && result.GetDidChangeProcessState() &&
2878 io_handler.GetFlags().Test(eHandleCommandFlagStopOnCrash)) {
2879 bool should_stop = false;
2880 TargetSP target_sp(m_debugger.GetTargetList().GetSelectedTarget());
2882 ProcessSP process_sp(target_sp->GetProcessSP());
2884 for (ThreadSP thread_sp : process_sp->GetThreadList().Threads()) {
2885 StopReason reason = thread_sp->GetStopReason();
2886 if ((reason == eStopReasonSignal || reason == eStopReasonException ||
2887 reason == eStopReasonInstrumentation) &&
2888 !result.GetAbnormalStopWasExpected()) {
2896 io_handler.SetIsDone(true);
2897 m_stopped_for_crash = true;
2902 bool CommandInterpreter::IOHandlerInterrupt(IOHandler &io_handler) {
2903 ExecutionContext exe_ctx(GetExecutionContext());
2904 Process *process = exe_ctx.GetProcessPtr();
2906 if (InterruptCommand())
2910 StateType state = process->GetState();
2911 if (StateIsRunningState(state)) {
2913 return true; // Don't do any updating when we are running
2917 ScriptInterpreter *script_interpreter =
2918 m_debugger.GetScriptInterpreter(false);
2919 if (script_interpreter) {
2920 if (script_interpreter->Interrupt())
2926 void CommandInterpreter::GetLLDBCommandsFromIOHandler(
2927 const char *prompt, IOHandlerDelegate &delegate, bool asynchronously,
2929 Debugger &debugger = GetDebugger();
2930 IOHandlerSP io_handler_sp(
2931 new IOHandlerEditline(debugger, IOHandler::Type::CommandList,
2932 "lldb", // Name of input reader for history
2933 llvm::StringRef::withNullAsEmpty(prompt), // Prompt
2934 llvm::StringRef(), // Continuation prompt
2935 true, // Get multiple lines
2936 debugger.GetUseColor(),
2937 0, // Don't show line numbers
2938 delegate, // IOHandlerDelegate
2939 nullptr)); // FileShadowCollector
2941 if (io_handler_sp) {
2942 io_handler_sp->SetUserData(baton);
2944 debugger.PushIOHandler(io_handler_sp);
2946 debugger.RunIOHandler(io_handler_sp);
2950 void CommandInterpreter::GetPythonCommandsFromIOHandler(
2951 const char *prompt, IOHandlerDelegate &delegate, bool asynchronously,
2953 Debugger &debugger = GetDebugger();
2954 IOHandlerSP io_handler_sp(
2955 new IOHandlerEditline(debugger, IOHandler::Type::PythonCode,
2956 "lldb-python", // Name of input reader for history
2957 llvm::StringRef::withNullAsEmpty(prompt), // Prompt
2958 llvm::StringRef(), // Continuation prompt
2959 true, // Get multiple lines
2960 debugger.GetUseColor(),
2961 0, // Don't show line numbers
2962 delegate, // IOHandlerDelegate
2963 nullptr)); // FileShadowCollector
2965 if (io_handler_sp) {
2966 io_handler_sp->SetUserData(baton);
2968 debugger.PushIOHandler(io_handler_sp);
2970 debugger.RunIOHandler(io_handler_sp);
2974 bool CommandInterpreter::IsActive() {
2975 return m_debugger.IsTopIOHandler(m_command_io_handler_sp);
2979 CommandInterpreter::GetIOHandler(bool force_create,
2980 CommandInterpreterRunOptions *options) {
2981 // Always re-create the IOHandlerEditline in case the input changed. The old
2982 // instance might have had a non-interactive input and now it does or vice
2984 if (force_create || !m_command_io_handler_sp) {
2985 // Always re-create the IOHandlerEditline in case the input changed. The
2986 // old instance might have had a non-interactive input and now it does or
2991 if (options->m_stop_on_continue == eLazyBoolYes)
2992 flags |= eHandleCommandFlagStopOnContinue;
2993 if (options->m_stop_on_error == eLazyBoolYes)
2994 flags |= eHandleCommandFlagStopOnError;
2995 if (options->m_stop_on_crash == eLazyBoolYes)
2996 flags |= eHandleCommandFlagStopOnCrash;
2997 if (options->m_echo_commands != eLazyBoolNo)
2998 flags |= eHandleCommandFlagEchoCommand;
2999 if (options->m_echo_comment_commands != eLazyBoolNo)
3000 flags |= eHandleCommandFlagEchoCommentCommand;
3001 if (options->m_print_results != eLazyBoolNo)
3002 flags |= eHandleCommandFlagPrintResult;
3003 if (options->m_print_errors != eLazyBoolNo)
3004 flags |= eHandleCommandFlagPrintErrors;
3006 flags = eHandleCommandFlagEchoCommand | eHandleCommandFlagPrintResult |
3007 eHandleCommandFlagPrintErrors;
3010 m_command_io_handler_sp = std::make_shared<IOHandlerEditline>(
3011 m_debugger, IOHandler::Type::CommandInterpreter,
3012 m_debugger.GetInputFile(), m_debugger.GetOutputFile(),
3013 m_debugger.GetErrorFile(), flags, "lldb", m_debugger.GetPrompt(),
3014 llvm::StringRef(), // Continuation prompt
3015 false, // Don't enable multiple line input, just single line commands
3016 m_debugger.GetUseColor(),
3017 0, // Don't show line numbers
3018 *this, // IOHandlerDelegate
3019 GetDebugger().GetInputRecorder());
3021 return m_command_io_handler_sp;
3024 void CommandInterpreter::RunCommandInterpreter(
3025 bool auto_handle_events, bool spawn_thread,
3026 CommandInterpreterRunOptions &options) {
3027 // Always re-create the command interpreter when we run it in case any file
3028 // handles have changed.
3029 bool force_create = true;
3030 m_debugger.PushIOHandler(GetIOHandler(force_create, &options));
3031 m_stopped_for_crash = false;
3033 if (auto_handle_events)
3034 m_debugger.StartEventHandlerThread();
3037 m_debugger.StartIOHandlerThread();
3039 m_debugger.ExecuteIOHandlers();
3041 if (auto_handle_events)
3042 m_debugger.StopEventHandlerThread();
3047 CommandInterpreter::ResolveCommandImpl(std::string &command_line,
3048 CommandReturnObject &result) {
3049 std::string scratch_command(command_line); // working copy so we don't modify
3050 // command_line unless we succeed
3051 CommandObject *cmd_obj = nullptr;
3052 StreamString revised_command_line;
3053 bool wants_raw_input = false;
3054 size_t actual_cmd_name_len = 0;
3055 std::string next_word;
3059 char quote_char = '\0';
3061 ExtractCommand(scratch_command, next_word, suffix, quote_char);
3062 if (cmd_obj == nullptr) {
3063 std::string full_name;
3064 bool is_alias = GetAliasFullName(next_word, full_name);
3065 cmd_obj = GetCommandObject(next_word, &matches);
3066 bool is_real_command =
3067 (!is_alias) || (cmd_obj != nullptr && !cmd_obj->IsAlias());
3068 if (!is_real_command) {
3070 std::string alias_result;
3072 BuildAliasResult(full_name, scratch_command, alias_result, result);
3073 revised_command_line.Printf("%s", alias_result.c_str());
3075 wants_raw_input = cmd_obj->WantsRawCommandString();
3076 actual_cmd_name_len = cmd_obj->GetCommandName().size();
3080 llvm::StringRef cmd_name = cmd_obj->GetCommandName();
3081 actual_cmd_name_len += cmd_name.size();
3082 revised_command_line.Printf("%s", cmd_name.str().c_str());
3083 wants_raw_input = cmd_obj->WantsRawCommandString();
3085 revised_command_line.Printf("%s", next_word.c_str());
3089 if (cmd_obj->IsMultiwordObject()) {
3090 CommandObject *sub_cmd_obj =
3091 cmd_obj->GetSubcommandObject(next_word.c_str());
3093 // The subcommand's name includes the parent command's name, so
3094 // restart rather than append to the revised_command_line.
3095 llvm::StringRef sub_cmd_name = sub_cmd_obj->GetCommandName();
3096 actual_cmd_name_len = sub_cmd_name.size() + 1;
3097 revised_command_line.Clear();
3098 revised_command_line.Printf("%s", sub_cmd_name.str().c_str());
3099 cmd_obj = sub_cmd_obj;
3100 wants_raw_input = cmd_obj->WantsRawCommandString();
3103 revised_command_line.Printf(" %c%s%s%c", quote_char,
3104 next_word.c_str(), suffix.c_str(),
3107 revised_command_line.Printf(" %s%s", next_word.c_str(),
3113 revised_command_line.Printf(" %c%s%s%c", quote_char,
3114 next_word.c_str(), suffix.c_str(),
3117 revised_command_line.Printf(" %s%s", next_word.c_str(),
3123 if (cmd_obj == nullptr) {
3124 const size_t num_matches = matches.GetSize();
3125 if (matches.GetSize() > 1) {
3126 StreamString error_msg;
3127 error_msg.Printf("Ambiguous command '%s'. Possible matches:\n",
3130 for (uint32_t i = 0; i < num_matches; ++i) {
3131 error_msg.Printf("\t%s\n", matches.GetStringAtIndex(i));
3133 result.AppendRawError(error_msg.GetString());
3135 // We didn't have only one match, otherwise we wouldn't get here.
3136 lldbassert(num_matches == 0);
3137 result.AppendErrorWithFormat("'%s' is not a valid command.\n",
3140 result.SetStatus(eReturnStatusFailed);
3144 if (cmd_obj->IsMultiwordObject()) {
3145 if (!suffix.empty()) {
3146 result.AppendErrorWithFormat(
3147 "command '%s' did not recognize '%s%s%s' as valid (subcommand "
3148 "might be invalid).\n",
3149 cmd_obj->GetCommandName().str().c_str(),
3150 next_word.empty() ? "" : next_word.c_str(),
3151 next_word.empty() ? " -- " : " ", suffix.c_str());
3152 result.SetStatus(eReturnStatusFailed);
3156 // If we found a normal command, we are done
3158 if (!suffix.empty()) {
3159 switch (suffix[0]) {
3161 // GDB format suffixes
3163 Options *command_options = cmd_obj->GetOptions();
3164 if (command_options &&
3165 command_options->SupportsLongOption("gdb-format")) {
3166 std::string gdb_format_option("--gdb-format=");
3167 gdb_format_option += (suffix.c_str() + 1);
3169 std::string cmd = revised_command_line.GetString();
3170 size_t arg_terminator_idx = FindArgumentTerminator(cmd);
3171 if (arg_terminator_idx != std::string::npos) {
3172 // Insert the gdb format option before the "--" that terminates
3174 gdb_format_option.append(1, ' ');
3175 cmd.insert(arg_terminator_idx, gdb_format_option);
3176 revised_command_line.Clear();
3177 revised_command_line.PutCString(cmd);
3179 revised_command_line.Printf(" %s", gdb_format_option.c_str());
3181 if (wants_raw_input &&
3182 FindArgumentTerminator(cmd) == std::string::npos)
3183 revised_command_line.PutCString(" --");
3185 result.AppendErrorWithFormat(
3186 "the '%s' command doesn't support the --gdb-format option\n",
3187 cmd_obj->GetCommandName().str().c_str());
3188 result.SetStatus(eReturnStatusFailed);
3195 result.AppendErrorWithFormat(
3196 "unknown command shorthand suffix: '%s'\n", suffix.c_str());
3197 result.SetStatus(eReturnStatusFailed);
3202 if (scratch_command.empty())
3206 if (!scratch_command.empty())
3207 revised_command_line.Printf(" %s", scratch_command.c_str());
3209 if (cmd_obj != nullptr)
3210 command_line = revised_command_line.GetString();