1 //===-- CommandInterpreter.cpp --------------------------------------------===//
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 //===----------------------------------------------------------------------===//
16 #include "Commands/CommandObjectApropos.h"
17 #include "Commands/CommandObjectBreakpoint.h"
18 #include "Commands/CommandObjectCommands.h"
19 #include "Commands/CommandObjectDWIMPrint.h"
20 #include "Commands/CommandObjectDiagnostics.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/CommandObjectRegexCommand.h"
34 #include "Commands/CommandObjectRegister.h"
35 #include "Commands/CommandObjectScript.h"
36 #include "Commands/CommandObjectSession.h"
37 #include "Commands/CommandObjectSettings.h"
38 #include "Commands/CommandObjectSource.h"
39 #include "Commands/CommandObjectStats.h"
40 #include "Commands/CommandObjectTarget.h"
41 #include "Commands/CommandObjectThread.h"
42 #include "Commands/CommandObjectTrace.h"
43 #include "Commands/CommandObjectType.h"
44 #include "Commands/CommandObjectVersion.h"
45 #include "Commands/CommandObjectWatchpoint.h"
47 #include "lldb/Core/Debugger.h"
48 #include "lldb/Core/PluginManager.h"
49 #include "lldb/Host/StreamFile.h"
50 #include "lldb/Utility/LLDBLog.h"
51 #include "lldb/Utility/Log.h"
52 #include "lldb/Utility/State.h"
53 #include "lldb/Utility/Stream.h"
54 #include "lldb/Utility/Timer.h"
56 #include "lldb/Host/Config.h"
57 #if LLDB_ENABLE_LIBEDIT
58 #include "lldb/Host/Editline.h"
60 #include "lldb/Host/File.h"
61 #include "lldb/Host/FileCache.h"
62 #include "lldb/Host/Host.h"
63 #include "lldb/Host/HostInfo.h"
65 #include "lldb/Interpreter/CommandCompletions.h"
66 #include "lldb/Interpreter/CommandInterpreter.h"
67 #include "lldb/Interpreter/CommandReturnObject.h"
68 #include "lldb/Interpreter/OptionValueProperties.h"
69 #include "lldb/Interpreter/Options.h"
70 #include "lldb/Interpreter/Property.h"
71 #include "lldb/Utility/Args.h"
73 #include "lldb/Target/Language.h"
74 #include "lldb/Target/Process.h"
75 #include "lldb/Target/StopInfo.h"
76 #include "lldb/Target/TargetList.h"
77 #include "lldb/Target/Thread.h"
78 #include "lldb/Target/UnixSignals.h"
80 #include "llvm/ADT/STLExtras.h"
81 #include "llvm/ADT/ScopeExit.h"
82 #include "llvm/ADT/SmallString.h"
83 #include "llvm/Support/FormatAdapters.h"
84 #include "llvm/Support/Path.h"
85 #include "llvm/Support/PrettyStackTrace.h"
86 #include "llvm/Support/ScopedPrinter.h"
88 #if defined(__APPLE__)
89 #include <TargetConditionals.h>
93 using namespace lldb_private
;
95 static const char *k_white_space
= " \t\v";
97 static constexpr const char *InitFileWarning
=
98 "There is a .lldbinit file in the current directory which is not being "
100 "To silence this warning without sourcing in the local .lldbinit,\n"
101 "add the following to the lldbinit file in your home directory:\n"
102 " settings set target.load-cwd-lldbinit false\n"
103 "To allow lldb to source .lldbinit files in the current working "
105 "set the value of this variable to true. Only do so if you understand "
107 "accept the security risk.";
109 const char *CommandInterpreter::g_no_argument
= "<no-argument>";
110 const char *CommandInterpreter::g_need_argument
= "<need-argument>";
111 const char *CommandInterpreter::g_argument
= "<argument>";
114 #define LLDB_PROPERTIES_interpreter
115 #include "InterpreterProperties.inc"
118 #define LLDB_PROPERTIES_interpreter
119 #include "InterpreterPropertiesEnum.inc"
122 ConstString
&CommandInterpreter::GetStaticBroadcasterClass() {
123 static ConstString
class_name("lldb.commandInterpreter");
127 CommandInterpreter::CommandInterpreter(Debugger
&debugger
,
128 bool synchronous_execution
)
129 : Broadcaster(debugger
.GetBroadcasterManager(),
130 CommandInterpreter::GetStaticBroadcasterClass().AsCString()),
132 OptionValuePropertiesSP(new OptionValueProperties("interpreter"))),
133 IOHandlerDelegate(IOHandlerDelegate::Completion::LLDBCommand
),
134 m_debugger(debugger
), m_synchronous_execution(true),
135 m_skip_lldbinit_files(false), m_skip_app_init_files(false),
136 m_comment_char('#'), m_batch_command_mode(false),
137 m_truncation_warning(eNoOmission
), m_max_depth_warning(eNoOmission
),
138 m_command_source_depth(0) {
139 SetEventName(eBroadcastBitThreadShouldExit
, "thread-should-exit");
140 SetEventName(eBroadcastBitResetPrompt
, "reset-prompt");
141 SetEventName(eBroadcastBitQuitCommandReceived
, "quit");
142 SetSynchronous(synchronous_execution
);
143 CheckInWithManager();
144 m_collection_sp
->Initialize(g_interpreter_properties
);
147 bool CommandInterpreter::GetExpandRegexAliases() const {
148 const uint32_t idx
= ePropertyExpandRegexAliases
;
149 return GetPropertyAtIndexAs
<bool>(
150 idx
, g_interpreter_properties
[idx
].default_uint_value
!= 0);
153 bool CommandInterpreter::GetPromptOnQuit() const {
154 const uint32_t idx
= ePropertyPromptOnQuit
;
155 return GetPropertyAtIndexAs
<bool>(
156 idx
, g_interpreter_properties
[idx
].default_uint_value
!= 0);
159 void CommandInterpreter::SetPromptOnQuit(bool enable
) {
160 const uint32_t idx
= ePropertyPromptOnQuit
;
161 SetPropertyAtIndex(idx
, enable
);
164 bool CommandInterpreter::GetSaveSessionOnQuit() const {
165 const uint32_t idx
= ePropertySaveSessionOnQuit
;
166 return GetPropertyAtIndexAs
<bool>(
167 idx
, g_interpreter_properties
[idx
].default_uint_value
!= 0);
170 void CommandInterpreter::SetSaveSessionOnQuit(bool enable
) {
171 const uint32_t idx
= ePropertySaveSessionOnQuit
;
172 SetPropertyAtIndex(idx
, enable
);
175 bool CommandInterpreter::GetOpenTranscriptInEditor() const {
176 const uint32_t idx
= ePropertyOpenTranscriptInEditor
;
177 return GetPropertyAtIndexAs
<bool>(
178 idx
, g_interpreter_properties
[idx
].default_uint_value
!= 0);
181 void CommandInterpreter::SetOpenTranscriptInEditor(bool enable
) {
182 const uint32_t idx
= ePropertyOpenTranscriptInEditor
;
183 SetPropertyAtIndex(idx
, enable
);
186 FileSpec
CommandInterpreter::GetSaveSessionDirectory() const {
187 const uint32_t idx
= ePropertySaveSessionDirectory
;
188 return GetPropertyAtIndexAs
<FileSpec
>(idx
, {});
191 void CommandInterpreter::SetSaveSessionDirectory(llvm::StringRef path
) {
192 const uint32_t idx
= ePropertySaveSessionDirectory
;
193 SetPropertyAtIndex(idx
, path
);
196 bool CommandInterpreter::GetEchoCommands() const {
197 const uint32_t idx
= ePropertyEchoCommands
;
198 return GetPropertyAtIndexAs
<bool>(
199 idx
, g_interpreter_properties
[idx
].default_uint_value
!= 0);
202 void CommandInterpreter::SetEchoCommands(bool enable
) {
203 const uint32_t idx
= ePropertyEchoCommands
;
204 SetPropertyAtIndex(idx
, enable
);
207 bool CommandInterpreter::GetEchoCommentCommands() const {
208 const uint32_t idx
= ePropertyEchoCommentCommands
;
209 return GetPropertyAtIndexAs
<bool>(
210 idx
, g_interpreter_properties
[idx
].default_uint_value
!= 0);
213 void CommandInterpreter::SetEchoCommentCommands(bool enable
) {
214 const uint32_t idx
= ePropertyEchoCommentCommands
;
215 SetPropertyAtIndex(idx
, enable
);
218 void CommandInterpreter::AllowExitCodeOnQuit(bool allow
) {
219 m_allow_exit_code
= allow
;
221 m_quit_exit_code
.reset();
224 bool CommandInterpreter::SetQuitExitCode(int exit_code
) {
225 if (!m_allow_exit_code
)
227 m_quit_exit_code
= exit_code
;
231 int CommandInterpreter::GetQuitExitCode(bool &exited
) const {
232 exited
= m_quit_exit_code
.has_value();
234 return *m_quit_exit_code
;
238 void CommandInterpreter::ResolveCommand(const char *command_line
,
239 CommandReturnObject
&result
) {
240 std::string command
= command_line
;
241 if (ResolveCommandImpl(command
, result
) != nullptr) {
242 result
.AppendMessageWithFormat("%s", command
.c_str());
243 result
.SetStatus(eReturnStatusSuccessFinishResult
);
247 bool CommandInterpreter::GetStopCmdSourceOnError() const {
248 const uint32_t idx
= ePropertyStopCmdSourceOnError
;
249 return GetPropertyAtIndexAs
<bool>(
250 idx
, g_interpreter_properties
[idx
].default_uint_value
!= 0);
253 bool CommandInterpreter::GetSpaceReplPrompts() const {
254 const uint32_t idx
= ePropertySpaceReplPrompts
;
255 return GetPropertyAtIndexAs
<bool>(
256 idx
, g_interpreter_properties
[idx
].default_uint_value
!= 0);
259 bool CommandInterpreter::GetRepeatPreviousCommand() const {
260 const uint32_t idx
= ePropertyRepeatPreviousCommand
;
261 return GetPropertyAtIndexAs
<bool>(
262 idx
, g_interpreter_properties
[idx
].default_uint_value
!= 0);
265 bool CommandInterpreter::GetRequireCommandOverwrite() const {
266 const uint32_t idx
= ePropertyRequireCommandOverwrite
;
267 return GetPropertyAtIndexAs
<bool>(
268 idx
, g_interpreter_properties
[idx
].default_uint_value
!= 0);
271 void CommandInterpreter::Initialize() {
274 CommandReturnObject
result(m_debugger
.GetUseColor());
276 LoadCommandDictionary();
278 // An alias arguments vector to reuse - reset it before use...
279 OptionArgVectorSP
alias_arguments_vector_sp(new OptionArgVector
);
281 // Set up some initial aliases.
282 CommandObjectSP cmd_obj_sp
= GetCommandSPExact("quit");
284 AddAlias("q", cmd_obj_sp
);
285 AddAlias("exit", cmd_obj_sp
);
288 cmd_obj_sp
= GetCommandSPExact("_regexp-attach");
290 AddAlias("attach", cmd_obj_sp
)->SetSyntax(cmd_obj_sp
->GetSyntax());
292 cmd_obj_sp
= GetCommandSPExact("process detach");
294 AddAlias("detach", cmd_obj_sp
);
297 cmd_obj_sp
= GetCommandSPExact("process continue");
299 AddAlias("c", cmd_obj_sp
);
300 AddAlias("continue", cmd_obj_sp
);
303 cmd_obj_sp
= GetCommandSPExact("_regexp-break");
305 AddAlias("b", cmd_obj_sp
)->SetSyntax(cmd_obj_sp
->GetSyntax());
307 cmd_obj_sp
= GetCommandSPExact("_regexp-tbreak");
309 AddAlias("tbreak", cmd_obj_sp
)->SetSyntax(cmd_obj_sp
->GetSyntax());
311 cmd_obj_sp
= GetCommandSPExact("thread step-inst");
313 AddAlias("stepi", cmd_obj_sp
);
314 AddAlias("si", cmd_obj_sp
);
317 cmd_obj_sp
= GetCommandSPExact("thread step-inst-over");
319 AddAlias("nexti", cmd_obj_sp
);
320 AddAlias("ni", cmd_obj_sp
);
323 cmd_obj_sp
= GetCommandSPExact("thread step-in");
325 AddAlias("s", cmd_obj_sp
);
326 AddAlias("step", cmd_obj_sp
);
327 CommandAlias
*sif_alias
= AddAlias(
328 "sif", cmd_obj_sp
, "--end-linenumber block --step-in-target %1");
330 sif_alias
->SetHelp("Step through the current block, stopping if you step "
331 "directly into a function whose name matches the "
332 "TargetFunctionName.");
333 sif_alias
->SetSyntax("sif <TargetFunctionName>");
337 cmd_obj_sp
= GetCommandSPExact("thread step-over");
339 AddAlias("n", cmd_obj_sp
);
340 AddAlias("next", cmd_obj_sp
);
343 cmd_obj_sp
= GetCommandSPExact("thread step-out");
345 AddAlias("finish", cmd_obj_sp
);
348 cmd_obj_sp
= GetCommandSPExact("frame select");
350 AddAlias("f", cmd_obj_sp
);
353 cmd_obj_sp
= GetCommandSPExact("thread select");
355 AddAlias("t", cmd_obj_sp
);
358 cmd_obj_sp
= GetCommandSPExact("_regexp-jump");
360 AddAlias("j", cmd_obj_sp
)->SetSyntax(cmd_obj_sp
->GetSyntax());
361 AddAlias("jump", cmd_obj_sp
)->SetSyntax(cmd_obj_sp
->GetSyntax());
364 cmd_obj_sp
= GetCommandSPExact("_regexp-list");
366 AddAlias("l", cmd_obj_sp
)->SetSyntax(cmd_obj_sp
->GetSyntax());
367 AddAlias("list", cmd_obj_sp
)->SetSyntax(cmd_obj_sp
->GetSyntax());
370 cmd_obj_sp
= GetCommandSPExact("_regexp-env");
372 AddAlias("env", cmd_obj_sp
)->SetSyntax(cmd_obj_sp
->GetSyntax());
374 cmd_obj_sp
= GetCommandSPExact("memory read");
376 AddAlias("x", cmd_obj_sp
);
378 cmd_obj_sp
= GetCommandSPExact("_regexp-up");
380 AddAlias("up", cmd_obj_sp
)->SetSyntax(cmd_obj_sp
->GetSyntax());
382 cmd_obj_sp
= GetCommandSPExact("_regexp-down");
384 AddAlias("down", cmd_obj_sp
)->SetSyntax(cmd_obj_sp
->GetSyntax());
386 cmd_obj_sp
= GetCommandSPExact("_regexp-display");
388 AddAlias("display", cmd_obj_sp
)->SetSyntax(cmd_obj_sp
->GetSyntax());
390 cmd_obj_sp
= GetCommandSPExact("disassemble");
392 AddAlias("dis", cmd_obj_sp
);
394 cmd_obj_sp
= GetCommandSPExact("disassemble");
396 AddAlias("di", cmd_obj_sp
);
398 cmd_obj_sp
= GetCommandSPExact("_regexp-undisplay");
400 AddAlias("undisplay", cmd_obj_sp
)->SetSyntax(cmd_obj_sp
->GetSyntax());
402 cmd_obj_sp
= GetCommandSPExact("_regexp-bt");
404 AddAlias("bt", cmd_obj_sp
)->SetSyntax(cmd_obj_sp
->GetSyntax());
406 cmd_obj_sp
= GetCommandSPExact("target create");
408 AddAlias("file", cmd_obj_sp
);
410 cmd_obj_sp
= GetCommandSPExact("target modules");
412 AddAlias("image", cmd_obj_sp
);
414 alias_arguments_vector_sp
= std::make_shared
<OptionArgVector
>();
416 cmd_obj_sp
= GetCommandSPExact("dwim-print");
418 AddAlias("p", cmd_obj_sp
, "--")->SetHelpLong("");
419 AddAlias("print", cmd_obj_sp
, "--")->SetHelpLong("");
420 if (auto *po
= AddAlias("po", cmd_obj_sp
, "-O --")) {
421 po
->SetHelp("Evaluate an expression on the current thread. Displays any "
422 "returned value with formatting "
423 "controlled by the type's author.");
428 cmd_obj_sp
= GetCommandSPExact("expression");
430 AddAlias("call", cmd_obj_sp
, "--")->SetHelpLong("");
431 CommandAlias
*parray_alias
=
432 AddAlias("parray", cmd_obj_sp
, "--element-count %1 --");
434 parray_alias
->SetHelp
435 ("parray <COUNT> <EXPRESSION> -- lldb will evaluate EXPRESSION "
436 "to get a typed-pointer-to-an-array in memory, and will display "
437 "COUNT elements of that type from the array.");
438 parray_alias
->SetHelpLong("");
440 CommandAlias
*poarray_alias
= AddAlias("poarray", cmd_obj_sp
,
441 "--object-description --element-count %1 --");
443 poarray_alias
->SetHelp("poarray <COUNT> <EXPRESSION> -- lldb will "
444 "evaluate EXPRESSION to get the address of an array of COUNT "
445 "objects in memory, and will call po on them.");
446 poarray_alias
->SetHelpLong("");
450 cmd_obj_sp
= GetCommandSPExact("platform shell");
452 CommandAlias
*shell_alias
= AddAlias("shell", cmd_obj_sp
, " --host --");
454 shell_alias
->SetHelp("Run a shell command on the host.");
455 shell_alias
->SetHelpLong("");
456 shell_alias
->SetSyntax("shell <shell-command>");
460 cmd_obj_sp
= GetCommandSPExact("process kill");
462 AddAlias("kill", cmd_obj_sp
);
465 cmd_obj_sp
= GetCommandSPExact("process launch");
467 alias_arguments_vector_sp
= std::make_shared
<OptionArgVector
>();
468 #if defined(__APPLE__)
470 AddAlias("r", cmd_obj_sp
, "--");
471 AddAlias("run", cmd_obj_sp
, "--");
473 AddAlias("r", cmd_obj_sp
, "--shell-expand-args true --");
474 AddAlias("run", cmd_obj_sp
, "--shell-expand-args true --");
477 StreamString defaultshell
;
478 defaultshell
.Printf("--shell=%s --",
479 HostInfo::GetDefaultShell().GetPath().c_str());
480 AddAlias("r", cmd_obj_sp
, defaultshell
.GetString());
481 AddAlias("run", cmd_obj_sp
, defaultshell
.GetString());
485 cmd_obj_sp
= GetCommandSPExact("target symbols add");
487 AddAlias("add-dsym", cmd_obj_sp
);
490 cmd_obj_sp
= GetCommandSPExact("breakpoint set");
492 AddAlias("rbreak", cmd_obj_sp
, "--func-regex %1");
495 cmd_obj_sp
= GetCommandSPExact("frame variable");
497 AddAlias("v", cmd_obj_sp
);
498 AddAlias("var", cmd_obj_sp
);
499 AddAlias("vo", cmd_obj_sp
, "--object-description");
502 cmd_obj_sp
= GetCommandSPExact("register");
504 AddAlias("re", cmd_obj_sp
);
507 cmd_obj_sp
= GetCommandSPExact("session history");
509 AddAlias("history", cmd_obj_sp
);
512 cmd_obj_sp
= GetCommandSPExact("help");
514 AddAlias("h", cmd_obj_sp
);
518 void CommandInterpreter::Clear() {
519 m_command_io_handler_sp
.reset();
522 const char *CommandInterpreter::ProcessEmbeddedScriptCommands(const char *arg
) {
523 // This function has not yet been implemented.
525 // Look for any embedded script command
527 // get interpreter object from the command dictionary,
528 // call execute_one_command on it,
529 // get the results as a string,
530 // substitute that string for current stuff.
535 #define REGISTER_COMMAND_OBJECT(NAME, CLASS) \
536 m_command_dict[NAME] = std::make_shared<CLASS>(*this);
538 void CommandInterpreter::LoadCommandDictionary() {
541 REGISTER_COMMAND_OBJECT("apropos", CommandObjectApropos
);
542 REGISTER_COMMAND_OBJECT("breakpoint", CommandObjectMultiwordBreakpoint
);
543 REGISTER_COMMAND_OBJECT("command", CommandObjectMultiwordCommands
);
544 REGISTER_COMMAND_OBJECT("diagnostics", CommandObjectDiagnostics
);
545 REGISTER_COMMAND_OBJECT("disassemble", CommandObjectDisassemble
);
546 REGISTER_COMMAND_OBJECT("dwim-print", CommandObjectDWIMPrint
);
547 REGISTER_COMMAND_OBJECT("expression", CommandObjectExpression
);
548 REGISTER_COMMAND_OBJECT("frame", CommandObjectMultiwordFrame
);
549 REGISTER_COMMAND_OBJECT("gui", CommandObjectGUI
);
550 REGISTER_COMMAND_OBJECT("help", CommandObjectHelp
);
551 REGISTER_COMMAND_OBJECT("log", CommandObjectLog
);
552 REGISTER_COMMAND_OBJECT("memory", CommandObjectMemory
);
553 REGISTER_COMMAND_OBJECT("platform", CommandObjectPlatform
);
554 REGISTER_COMMAND_OBJECT("plugin", CommandObjectPlugin
);
555 REGISTER_COMMAND_OBJECT("process", CommandObjectMultiwordProcess
);
556 REGISTER_COMMAND_OBJECT("quit", CommandObjectQuit
);
557 REGISTER_COMMAND_OBJECT("register", CommandObjectRegister
);
558 REGISTER_COMMAND_OBJECT("script", CommandObjectScript
);
559 REGISTER_COMMAND_OBJECT("settings", CommandObjectMultiwordSettings
);
560 REGISTER_COMMAND_OBJECT("session", CommandObjectSession
);
561 REGISTER_COMMAND_OBJECT("source", CommandObjectMultiwordSource
);
562 REGISTER_COMMAND_OBJECT("statistics", CommandObjectStats
);
563 REGISTER_COMMAND_OBJECT("target", CommandObjectMultiwordTarget
);
564 REGISTER_COMMAND_OBJECT("thread", CommandObjectMultiwordThread
);
565 REGISTER_COMMAND_OBJECT("trace", CommandObjectTrace
);
566 REGISTER_COMMAND_OBJECT("type", CommandObjectType
);
567 REGISTER_COMMAND_OBJECT("version", CommandObjectVersion
);
568 REGISTER_COMMAND_OBJECT("watchpoint", CommandObjectMultiwordWatchpoint
);
569 REGISTER_COMMAND_OBJECT("language", CommandObjectLanguage
);
572 const char *break_regexes
[][2] = {
573 {"^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$",
574 "breakpoint set --file '%1' --line %2 --column %3"},
575 {"^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$",
576 "breakpoint set --file '%1' --line %2"},
577 {"^/([^/]+)/$", "breakpoint set --source-pattern-regexp '%1'"},
578 {"^([[:digit:]]+)[[:space:]]*$", "breakpoint set --line %1"},
579 {"^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "breakpoint set --address %1"},
580 {"^[\"']?([-+]?\\[.*\\])[\"']?[[:space:]]*$",
581 "breakpoint set --name '%1'"},
582 {"^(-.*)$", "breakpoint set %1"},
583 {"^(.*[^[:space:]])`(.*[^[:space:]])[[:space:]]*$",
584 "breakpoint set --name '%2' --shlib '%1'"},
585 {"^\\&(.*[^[:space:]])[[:space:]]*$",
586 "breakpoint set --name '%1' --skip-prologue=0"},
587 {"^[\"']?(.*[^[:space:]\"'])[\"']?[[:space:]]*$",
588 "breakpoint set --name '%1'"}};
591 size_t num_regexes
= std::size(break_regexes
);
593 std::unique_ptr
<CommandObjectRegexCommand
> break_regex_cmd_up(
594 new CommandObjectRegexCommand(
595 *this, "_regexp-break",
596 "Set a breakpoint using one of several shorthand formats.",
598 "_regexp-break <filename>:<linenum>:<colnum>\n"
599 " main.c:12:21 // Break at line 12 and column "
601 "_regexp-break <filename>:<linenum>\n"
602 " main.c:12 // Break at line 12 of "
604 "_regexp-break <linenum>\n"
605 " 12 // Break at line 12 of current "
607 "_regexp-break 0x<address>\n"
608 " 0x1234000 // Break at address "
610 "_regexp-break <name>\n"
611 " main // Break in 'main' after the "
613 "_regexp-break &<name>\n"
614 " &main // Break at first instruction "
616 "_regexp-break <module>`<name>\n"
617 " libc.so`malloc // Break in 'malloc' from "
619 "_regexp-break /<source-regex>/\n"
620 " /break here/ // Break on source lines in "
622 " // containing text 'break "
624 lldb::eSymbolCompletion
| lldb::eSourceFileCompletion
, false));
626 if (break_regex_cmd_up
) {
628 for (size_t i
= 0; i
< num_regexes
; i
++) {
629 success
= break_regex_cmd_up
->AddRegexCommand(break_regexes
[i
][0],
630 break_regexes
[i
][1]);
635 break_regex_cmd_up
->AddRegexCommand("^$", "breakpoint list --full");
638 CommandObjectSP
break_regex_cmd_sp(break_regex_cmd_up
.release());
639 m_command_dict
[std::string(break_regex_cmd_sp
->GetCommandName())] =
644 std::unique_ptr
<CommandObjectRegexCommand
> tbreak_regex_cmd_up(
645 new CommandObjectRegexCommand(
646 *this, "_regexp-tbreak",
647 "Set a one-shot breakpoint using one of several shorthand formats.",
649 "_regexp-break <filename>:<linenum>:<colnum>\n"
650 " main.c:12:21 // Break at line 12 and column "
652 "_regexp-break <filename>:<linenum>\n"
653 " main.c:12 // Break at line 12 of "
655 "_regexp-break <linenum>\n"
656 " 12 // Break at line 12 of current "
658 "_regexp-break 0x<address>\n"
659 " 0x1234000 // Break at address "
661 "_regexp-break <name>\n"
662 " main // Break in 'main' after the "
664 "_regexp-break &<name>\n"
665 " &main // Break at first instruction "
667 "_regexp-break <module>`<name>\n"
668 " libc.so`malloc // Break in 'malloc' from "
670 "_regexp-break /<source-regex>/\n"
671 " /break here/ // Break on source lines in "
673 " // containing text 'break "
675 lldb::eSymbolCompletion
| lldb::eSourceFileCompletion
, false));
677 if (tbreak_regex_cmd_up
) {
679 for (size_t i
= 0; i
< num_regexes
; i
++) {
680 std::string command
= break_regexes
[i
][1];
683 tbreak_regex_cmd_up
->AddRegexCommand(break_regexes
[i
][0], command
);
688 tbreak_regex_cmd_up
->AddRegexCommand("^$", "breakpoint list --full");
691 CommandObjectSP
tbreak_regex_cmd_sp(tbreak_regex_cmd_up
.release());
692 m_command_dict
[std::string(tbreak_regex_cmd_sp
->GetCommandName())] =
697 std::unique_ptr
<CommandObjectRegexCommand
> attach_regex_cmd_up(
698 new CommandObjectRegexCommand(
699 *this, "_regexp-attach", "Attach to process by ID or name.",
700 "_regexp-attach <pid> | <process-name>", 0, false));
701 if (attach_regex_cmd_up
) {
702 if (attach_regex_cmd_up
->AddRegexCommand("^([0-9]+)[[:space:]]*$",
703 "process attach --pid %1") &&
704 attach_regex_cmd_up
->AddRegexCommand(
705 "^(-.*|.* -.*)$", "process attach %1") && // Any options that are
706 // specified get passed to
708 attach_regex_cmd_up
->AddRegexCommand("^(.+)$",
709 "process attach --name '%1'") &&
710 attach_regex_cmd_up
->AddRegexCommand("^$", "process attach")) {
711 CommandObjectSP
attach_regex_cmd_sp(attach_regex_cmd_up
.release());
712 m_command_dict
[std::string(attach_regex_cmd_sp
->GetCommandName())] =
717 std::unique_ptr
<CommandObjectRegexCommand
> down_regex_cmd_up(
718 new CommandObjectRegexCommand(*this, "_regexp-down",
719 "Select a newer stack frame. Defaults to "
720 "moving one frame, a numeric argument can "
721 "specify an arbitrary number.",
722 "_regexp-down [<count>]", 0, false));
723 if (down_regex_cmd_up
) {
724 if (down_regex_cmd_up
->AddRegexCommand("^$", "frame select -r -1") &&
725 down_regex_cmd_up
->AddRegexCommand("^([0-9]+)$",
726 "frame select -r -%1")) {
727 CommandObjectSP
down_regex_cmd_sp(down_regex_cmd_up
.release());
728 m_command_dict
[std::string(down_regex_cmd_sp
->GetCommandName())] =
733 std::unique_ptr
<CommandObjectRegexCommand
> up_regex_cmd_up(
734 new CommandObjectRegexCommand(
736 "Select an older stack frame. Defaults to moving one "
737 "frame, a numeric argument can specify an arbitrary number.",
738 "_regexp-up [<count>]", 0, false));
739 if (up_regex_cmd_up
) {
740 if (up_regex_cmd_up
->AddRegexCommand("^$", "frame select -r 1") &&
741 up_regex_cmd_up
->AddRegexCommand("^([0-9]+)$", "frame select -r %1")) {
742 CommandObjectSP
up_regex_cmd_sp(up_regex_cmd_up
.release());
743 m_command_dict
[std::string(up_regex_cmd_sp
->GetCommandName())] =
748 std::unique_ptr
<CommandObjectRegexCommand
> display_regex_cmd_up(
749 new CommandObjectRegexCommand(
750 *this, "_regexp-display",
751 "Evaluate an expression at every stop (see 'help target stop-hook'.)",
752 "_regexp-display expression", 0, false));
753 if (display_regex_cmd_up
) {
754 if (display_regex_cmd_up
->AddRegexCommand(
755 "^(.+)$", "target stop-hook add -o \"expr -- %1\"")) {
756 CommandObjectSP
display_regex_cmd_sp(display_regex_cmd_up
.release());
757 m_command_dict
[std::string(display_regex_cmd_sp
->GetCommandName())] =
758 display_regex_cmd_sp
;
762 std::unique_ptr
<CommandObjectRegexCommand
> undisplay_regex_cmd_up(
763 new CommandObjectRegexCommand(*this, "_regexp-undisplay",
764 "Stop displaying expression at every "
765 "stop (specified by stop-hook index.)",
766 "_regexp-undisplay stop-hook-number", 0,
768 if (undisplay_regex_cmd_up
) {
769 if (undisplay_regex_cmd_up
->AddRegexCommand("^([0-9]+)$",
770 "target stop-hook delete %1")) {
771 CommandObjectSP
undisplay_regex_cmd_sp(undisplay_regex_cmd_up
.release());
772 m_command_dict
[std::string(undisplay_regex_cmd_sp
->GetCommandName())] =
773 undisplay_regex_cmd_sp
;
777 std::unique_ptr
<CommandObjectRegexCommand
> connect_gdb_remote_cmd_up(
778 new CommandObjectRegexCommand(
780 "Connect to a process via remote GDB server.\n"
781 "If no host is specifed, localhost is assumed.\n"
782 "gdb-remote is an abbreviation for 'process connect --plugin "
783 "gdb-remote connect://<hostname>:<port>'\n",
784 "gdb-remote [<hostname>:]<portnum>", 0, false));
785 if (connect_gdb_remote_cmd_up
) {
786 if (connect_gdb_remote_cmd_up
->AddRegexCommand(
787 "^([^:]+|\\[[0-9a-fA-F:]+.*\\]):([0-9]+)$",
788 "process connect --plugin gdb-remote connect://%1:%2") &&
789 connect_gdb_remote_cmd_up
->AddRegexCommand(
791 "process connect --plugin gdb-remote connect://localhost:%1")) {
792 CommandObjectSP
command_sp(connect_gdb_remote_cmd_up
.release());
793 m_command_dict
[std::string(command_sp
->GetCommandName())] = command_sp
;
797 std::unique_ptr
<CommandObjectRegexCommand
> connect_kdp_remote_cmd_up(
798 new CommandObjectRegexCommand(
800 "Connect to a process via remote KDP server.\n"
801 "If no UDP port is specified, port 41139 is assumed.\n"
802 "kdp-remote is an abbreviation for 'process connect --plugin "
803 "kdp-remote udp://<hostname>:<port>'\n",
804 "kdp-remote <hostname>[:<portnum>]", 0, false));
805 if (connect_kdp_remote_cmd_up
) {
806 if (connect_kdp_remote_cmd_up
->AddRegexCommand(
807 "^([^:]+:[[:digit:]]+)$",
808 "process connect --plugin kdp-remote udp://%1") &&
809 connect_kdp_remote_cmd_up
->AddRegexCommand(
810 "^(.+)$", "process connect --plugin kdp-remote udp://%1:41139")) {
811 CommandObjectSP
command_sp(connect_kdp_remote_cmd_up
.release());
812 m_command_dict
[std::string(command_sp
->GetCommandName())] = command_sp
;
816 std::unique_ptr
<CommandObjectRegexCommand
> bt_regex_cmd_up(
817 new CommandObjectRegexCommand(
819 "Show the current thread's call stack. Any numeric argument "
820 "displays at most that many "
821 "frames. The argument 'all' displays all threads. Use 'settings"
822 " set frame-format' to customize the printing of individual frames "
823 "and 'settings set thread-format' to customize the thread header.",
824 "bt [<digit> | all]", 0, false));
825 if (bt_regex_cmd_up
) {
826 // accept but don't document "bt -c <number>" -- before bt was a regex
827 // command if you wanted to backtrace three frames you would do "bt -c 3"
828 // but the intention is to have this emulate the gdb "bt" command and so
829 // now "bt 3" is the preferred form, in line with gdb.
830 if (bt_regex_cmd_up
->AddRegexCommand("^([[:digit:]]+)[[:space:]]*$",
831 "thread backtrace -c %1") &&
832 bt_regex_cmd_up
->AddRegexCommand("^-c ([[:digit:]]+)[[:space:]]*$",
833 "thread backtrace -c %1") &&
834 bt_regex_cmd_up
->AddRegexCommand("^all[[:space:]]*$", "thread backtrace all") &&
835 bt_regex_cmd_up
->AddRegexCommand("^[[:space:]]*$", "thread backtrace")) {
836 CommandObjectSP
command_sp(bt_regex_cmd_up
.release());
837 m_command_dict
[std::string(command_sp
->GetCommandName())] = command_sp
;
841 std::unique_ptr
<CommandObjectRegexCommand
> list_regex_cmd_up(
842 new CommandObjectRegexCommand(
843 *this, "_regexp-list",
844 "List relevant source code using one of several shorthand formats.",
846 "_regexp-list <file>:<line> // List around specific file/line\n"
847 "_regexp-list <line> // List current file around specified "
849 "_regexp-list <function-name> // List specified function\n"
850 "_regexp-list 0x<address> // List around specified address\n"
851 "_regexp-list -[<count>] // List previous <count> lines\n"
852 "_regexp-list // List subsequent lines",
853 lldb::eSourceFileCompletion
, false));
854 if (list_regex_cmd_up
) {
855 if (list_regex_cmd_up
->AddRegexCommand("^([0-9]+)[[:space:]]*$",
856 "source list --line %1") &&
857 list_regex_cmd_up
->AddRegexCommand(
858 "^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]"
860 "source list --file '%1' --line %2") &&
861 list_regex_cmd_up
->AddRegexCommand(
862 "^\\*?(0x[[:xdigit:]]+)[[:space:]]*$",
863 "source list --address %1") &&
864 list_regex_cmd_up
->AddRegexCommand("^-[[:space:]]*$",
865 "source list --reverse") &&
866 list_regex_cmd_up
->AddRegexCommand(
867 "^-([[:digit:]]+)[[:space:]]*$",
868 "source list --reverse --count %1") &&
869 list_regex_cmd_up
->AddRegexCommand("^(.+)$",
870 "source list --name \"%1\"") &&
871 list_regex_cmd_up
->AddRegexCommand("^$", "source list")) {
872 CommandObjectSP
list_regex_cmd_sp(list_regex_cmd_up
.release());
873 m_command_dict
[std::string(list_regex_cmd_sp
->GetCommandName())] =
878 std::unique_ptr
<CommandObjectRegexCommand
> env_regex_cmd_up(
879 new CommandObjectRegexCommand(
880 *this, "_regexp-env",
881 "Shorthand for viewing and setting environment variables.",
883 "_regexp-env // Show environment\n"
884 "_regexp-env <name>=<value> // Set an environment variable",
886 if (env_regex_cmd_up
) {
887 if (env_regex_cmd_up
->AddRegexCommand("^$",
888 "settings show target.env-vars") &&
889 env_regex_cmd_up
->AddRegexCommand("^([A-Za-z_][A-Za-z_0-9]*=.*)$",
890 "settings set target.env-vars %1")) {
891 CommandObjectSP
env_regex_cmd_sp(env_regex_cmd_up
.release());
892 m_command_dict
[std::string(env_regex_cmd_sp
->GetCommandName())] =
897 std::unique_ptr
<CommandObjectRegexCommand
> jump_regex_cmd_up(
898 new CommandObjectRegexCommand(
899 *this, "_regexp-jump", "Set the program counter to a new address.",
901 "_regexp-jump <line>\n"
902 "_regexp-jump +<line-offset> | -<line-offset>\n"
903 "_regexp-jump <file>:<line>\n"
904 "_regexp-jump *<addr>\n",
906 if (jump_regex_cmd_up
) {
907 if (jump_regex_cmd_up
->AddRegexCommand("^\\*(.*)$",
908 "thread jump --addr %1") &&
909 jump_regex_cmd_up
->AddRegexCommand("^([0-9]+)$",
910 "thread jump --line %1") &&
911 jump_regex_cmd_up
->AddRegexCommand("^([^:]+):([0-9]+)$",
912 "thread jump --file %1 --line %2") &&
913 jump_regex_cmd_up
->AddRegexCommand("^([+\\-][0-9]+)$",
914 "thread jump --by %1")) {
915 CommandObjectSP
jump_regex_cmd_sp(jump_regex_cmd_up
.release());
916 m_command_dict
[std::string(jump_regex_cmd_sp
->GetCommandName())] =
922 int CommandInterpreter::GetCommandNamesMatchingPartialString(
923 const char *cmd_str
, bool include_aliases
, StringList
&matches
,
924 StringList
&descriptions
) {
925 AddNamesMatchingPartialString(m_command_dict
, cmd_str
, matches
,
928 if (include_aliases
) {
929 AddNamesMatchingPartialString(m_alias_dict
, cmd_str
, matches
,
933 return matches
.GetSize();
936 CommandObjectMultiword
*CommandInterpreter::VerifyUserMultiwordCmdPath(
937 Args
&path
, bool leaf_is_command
, Status
&result
) {
940 auto get_multi_or_report_error
=
941 [&result
](CommandObjectSP cmd_sp
,
942 const char *name
) -> CommandObjectMultiword
* {
944 result
.SetErrorStringWithFormat("Path component: '%s' not found", name
);
947 if (!cmd_sp
->IsUserCommand()) {
948 result
.SetErrorStringWithFormat("Path component: '%s' is not a user "
953 CommandObjectMultiword
*cmd_as_multi
= cmd_sp
->GetAsMultiwordCommand();
955 result
.SetErrorStringWithFormat("Path component: '%s' is not a container "
963 size_t num_args
= path
.GetArgumentCount();
965 result
.SetErrorString("empty command path");
969 if (num_args
== 1 && leaf_is_command
) {
970 // We just got a leaf command to be added to the root. That's not an error,
971 // just return null for the container.
975 // Start by getting the root command from the interpreter.
976 const char *cur_name
= path
.GetArgumentAtIndex(0);
977 CommandObjectSP cur_cmd_sp
= GetCommandSPExact(cur_name
);
978 CommandObjectMultiword
*cur_as_multi
=
979 get_multi_or_report_error(cur_cmd_sp
, cur_name
);
980 if (cur_as_multi
== nullptr)
983 size_t num_path_elements
= num_args
- (leaf_is_command
? 1 : 0);
984 for (size_t cursor
= 1; cursor
< num_path_elements
&& cur_as_multi
!= nullptr;
986 cur_name
= path
.GetArgumentAtIndex(cursor
);
987 cur_cmd_sp
= cur_as_multi
->GetSubcommandSPExact(cur_name
);
988 cur_as_multi
= get_multi_or_report_error(cur_cmd_sp
, cur_name
);
994 CommandInterpreter::GetCommandSP(llvm::StringRef cmd_str
, bool include_aliases
,
995 bool exact
, StringList
*matches
,
996 StringList
*descriptions
) const {
997 CommandObjectSP command_sp
;
999 std::string cmd
= std::string(cmd_str
);
1001 if (HasCommands()) {
1002 auto pos
= m_command_dict
.find(cmd
);
1003 if (pos
!= m_command_dict
.end())
1004 command_sp
= pos
->second
;
1007 if (include_aliases
&& HasAliases()) {
1008 auto alias_pos
= m_alias_dict
.find(cmd
);
1009 if (alias_pos
!= m_alias_dict
.end())
1010 command_sp
= alias_pos
->second
;
1013 if (HasUserCommands()) {
1014 auto pos
= m_user_dict
.find(cmd
);
1015 if (pos
!= m_user_dict
.end())
1016 command_sp
= pos
->second
;
1019 if (HasUserMultiwordCommands()) {
1020 auto pos
= m_user_mw_dict
.find(cmd
);
1021 if (pos
!= m_user_mw_dict
.end())
1022 command_sp
= pos
->second
;
1025 if (!exact
&& !command_sp
) {
1026 // We will only get into here if we didn't find any exact matches.
1028 CommandObjectSP user_match_sp
, user_mw_match_sp
, alias_match_sp
,
1031 StringList local_matches
;
1032 if (matches
== nullptr)
1033 matches
= &local_matches
;
1035 unsigned int num_cmd_matches
= 0;
1036 unsigned int num_alias_matches
= 0;
1037 unsigned int num_user_matches
= 0;
1038 unsigned int num_user_mw_matches
= 0;
1040 // Look through the command dictionaries one by one, and if we get only one
1041 // match from any of them in toto, then return that, otherwise return an
1042 // empty CommandObjectSP and the list of matches.
1044 if (HasCommands()) {
1045 num_cmd_matches
= AddNamesMatchingPartialString(m_command_dict
, cmd_str
,
1046 *matches
, descriptions
);
1049 if (num_cmd_matches
== 1) {
1050 cmd
.assign(matches
->GetStringAtIndex(0));
1051 auto pos
= m_command_dict
.find(cmd
);
1052 if (pos
!= m_command_dict
.end())
1053 real_match_sp
= pos
->second
;
1056 if (include_aliases
&& HasAliases()) {
1057 num_alias_matches
= AddNamesMatchingPartialString(m_alias_dict
, cmd_str
,
1058 *matches
, descriptions
);
1061 if (num_alias_matches
== 1) {
1062 cmd
.assign(matches
->GetStringAtIndex(num_cmd_matches
));
1063 auto alias_pos
= m_alias_dict
.find(cmd
);
1064 if (alias_pos
!= m_alias_dict
.end())
1065 alias_match_sp
= alias_pos
->second
;
1068 if (HasUserCommands()) {
1069 num_user_matches
= AddNamesMatchingPartialString(m_user_dict
, cmd_str
,
1070 *matches
, descriptions
);
1073 if (num_user_matches
== 1) {
1075 matches
->GetStringAtIndex(num_cmd_matches
+ num_alias_matches
));
1077 auto pos
= m_user_dict
.find(cmd
);
1078 if (pos
!= m_user_dict
.end())
1079 user_match_sp
= pos
->second
;
1082 if (HasUserMultiwordCommands()) {
1083 num_user_mw_matches
= AddNamesMatchingPartialString(
1084 m_user_mw_dict
, cmd_str
, *matches
, descriptions
);
1087 if (num_user_mw_matches
== 1) {
1088 cmd
.assign(matches
->GetStringAtIndex(num_cmd_matches
+ num_alias_matches
+
1091 auto pos
= m_user_mw_dict
.find(cmd
);
1092 if (pos
!= m_user_mw_dict
.end())
1093 user_mw_match_sp
= pos
->second
;
1096 // If we got exactly one match, return that, otherwise return the match
1099 if (num_user_matches
+ num_user_mw_matches
+ num_cmd_matches
+
1100 num_alias_matches
==
1102 if (num_cmd_matches
)
1103 return real_match_sp
;
1104 else if (num_alias_matches
)
1105 return alias_match_sp
;
1106 else if (num_user_mw_matches
)
1107 return user_mw_match_sp
;
1109 return user_match_sp
;
1111 } else if (matches
&& command_sp
) {
1112 matches
->AppendString(cmd_str
);
1114 descriptions
->AppendString(command_sp
->GetHelp());
1120 bool CommandInterpreter::AddCommand(llvm::StringRef name
,
1121 const lldb::CommandObjectSP
&cmd_sp
,
1124 lldbassert((this == &cmd_sp
->GetCommandInterpreter()) &&
1125 "tried to add a CommandObject from a different interpreter");
1130 cmd_sp
->SetIsUserCommand(false);
1132 std::string
name_sstr(name
);
1133 auto name_iter
= m_command_dict
.find(name_sstr
);
1134 if (name_iter
!= m_command_dict
.end()) {
1135 if (!can_replace
|| !name_iter
->second
->IsRemovable())
1137 name_iter
->second
= cmd_sp
;
1139 m_command_dict
[name_sstr
] = cmd_sp
;
1144 Status
CommandInterpreter::AddUserCommand(llvm::StringRef name
,
1145 const lldb::CommandObjectSP
&cmd_sp
,
1149 lldbassert((this == &cmd_sp
->GetCommandInterpreter()) &&
1150 "tried to add a CommandObject from a different interpreter");
1152 result
.SetErrorString("can't use the empty string for a command name");
1155 // do not allow replacement of internal commands
1156 if (CommandExists(name
)) {
1157 result
.SetErrorString("can't replace builtin command");
1161 if (UserCommandExists(name
)) {
1163 result
.SetErrorString("user command exists and force replace not set");
1166 if (cmd_sp
->IsMultiwordObject()) {
1167 if (!m_user_mw_dict
[std::string(name
)]->IsRemovable()) {
1168 result
.SetErrorString(
1169 "can't replace explicitly non-removable multi-word command");
1173 if (!m_user_dict
[std::string(name
)]->IsRemovable()) {
1174 result
.SetErrorString("can't replace explicitly non-removable command");
1180 cmd_sp
->SetIsUserCommand(true);
1182 if (cmd_sp
->IsMultiwordObject())
1183 m_user_mw_dict
[std::string(name
)] = cmd_sp
;
1185 m_user_dict
[std::string(name
)] = cmd_sp
;
1190 CommandInterpreter::GetCommandSPExact(llvm::StringRef cmd_str
,
1191 bool include_aliases
) const {
1192 // Break up the command string into words, in case it's a multi-word command.
1193 Args
cmd_words(cmd_str
);
1195 if (cmd_str
.empty())
1198 if (cmd_words
.GetArgumentCount() == 1)
1199 return GetCommandSP(cmd_str
, include_aliases
, true);
1201 // We have a multi-word command (seemingly), so we need to do more work.
1202 // First, get the cmd_obj_sp for the first word in the command.
1203 CommandObjectSP cmd_obj_sp
=
1204 GetCommandSP(cmd_words
.GetArgumentAtIndex(0), include_aliases
, true);
1208 // Loop through the rest of the words in the command (everything passed in
1209 // was supposed to be part of a command name), and find the appropriate
1210 // sub-command SP for each command word....
1211 size_t end
= cmd_words
.GetArgumentCount();
1212 for (size_t i
= 1; i
< end
; ++i
) {
1213 if (!cmd_obj_sp
->IsMultiwordObject()) {
1214 // We have more words in the command name, but we don't have a
1215 // multiword object. Fail and return.
1219 cmd_obj_sp
= cmd_obj_sp
->GetSubcommandSP(cmd_words
.GetArgumentAtIndex(i
));
1221 // The sub-command name was invalid. Fail and return.
1226 // We successfully looped through all the command words and got valid
1227 // command objects for them.
1232 CommandInterpreter::GetCommandObject(llvm::StringRef cmd_str
,
1233 StringList
*matches
,
1234 StringList
*descriptions
) const {
1235 // Try to find a match among commands and aliases. Allowing inexact matches,
1236 // but perferring exact matches.
1237 return GetCommandSP(cmd_str
, /*include_aliases=*/true, /*exact=*/false,
1238 matches
, descriptions
)
1242 CommandObject
*CommandInterpreter::GetUserCommandObject(
1243 llvm::StringRef cmd
, StringList
*matches
, StringList
*descriptions
) const {
1244 std::string
cmd_str(cmd
);
1245 auto find_exact
= [&](const CommandObject::CommandMap
&map
) {
1246 auto found_elem
= map
.find(std::string(cmd
));
1247 if (found_elem
== map
.end())
1248 return (CommandObject
*)nullptr;
1249 CommandObject
*exact_cmd
= found_elem
->second
.get();
1252 matches
->AppendString(exact_cmd
->GetCommandName());
1254 descriptions
->AppendString(exact_cmd
->GetHelp());
1257 return (CommandObject
*)nullptr;
1260 CommandObject
*exact_cmd
= find_exact(GetUserCommands());
1264 exact_cmd
= find_exact(GetUserMultiwordCommands());
1268 // We didn't have an exact command, so now look for partial matches.
1269 StringList tmp_list
;
1270 StringList
*matches_ptr
= matches
? matches
: &tmp_list
;
1271 AddNamesMatchingPartialString(GetUserCommands(), cmd_str
, *matches_ptr
);
1272 AddNamesMatchingPartialString(GetUserMultiwordCommands(),
1273 cmd_str
, *matches_ptr
);
1278 bool CommandInterpreter::CommandExists(llvm::StringRef cmd
) const {
1279 return m_command_dict
.find(std::string(cmd
)) != m_command_dict
.end();
1282 bool CommandInterpreter::GetAliasFullName(llvm::StringRef cmd
,
1283 std::string
&full_name
) const {
1285 (m_alias_dict
.find(std::string(cmd
)) != m_alias_dict
.end());
1287 full_name
.assign(std::string(cmd
));
1291 size_t num_alias_matches
;
1293 AddNamesMatchingPartialString(m_alias_dict
, cmd
, matches
);
1294 if (num_alias_matches
== 1) {
1295 // Make sure this isn't shadowing a command in the regular command space:
1296 StringList regular_matches
;
1297 const bool include_aliases
= false;
1298 const bool exact
= false;
1299 CommandObjectSP
cmd_obj_sp(
1300 GetCommandSP(cmd
, include_aliases
, exact
, ®ular_matches
));
1301 if (cmd_obj_sp
|| regular_matches
.GetSize() > 0)
1304 full_name
.assign(matches
.GetStringAtIndex(0));
1312 bool CommandInterpreter::AliasExists(llvm::StringRef cmd
) const {
1313 return m_alias_dict
.find(std::string(cmd
)) != m_alias_dict
.end();
1316 bool CommandInterpreter::UserCommandExists(llvm::StringRef cmd
) const {
1317 return m_user_dict
.find(std::string(cmd
)) != m_user_dict
.end();
1320 bool CommandInterpreter::UserMultiwordCommandExists(llvm::StringRef cmd
) const {
1321 return m_user_mw_dict
.find(std::string(cmd
)) != m_user_mw_dict
.end();
1325 CommandInterpreter::AddAlias(llvm::StringRef alias_name
,
1326 lldb::CommandObjectSP
&command_obj_sp
,
1327 llvm::StringRef args_string
) {
1328 if (command_obj_sp
.get())
1329 lldbassert((this == &command_obj_sp
->GetCommandInterpreter()) &&
1330 "tried to add a CommandObject from a different interpreter");
1332 std::unique_ptr
<CommandAlias
> command_alias_up(
1333 new CommandAlias(*this, command_obj_sp
, args_string
, alias_name
));
1335 if (command_alias_up
&& command_alias_up
->IsValid()) {
1336 m_alias_dict
[std::string(alias_name
)] =
1337 CommandObjectSP(command_alias_up
.get());
1338 return command_alias_up
.release();
1344 bool CommandInterpreter::RemoveAlias(llvm::StringRef alias_name
) {
1345 auto pos
= m_alias_dict
.find(std::string(alias_name
));
1346 if (pos
!= m_alias_dict
.end()) {
1347 m_alias_dict
.erase(pos
);
1353 bool CommandInterpreter::RemoveCommand(llvm::StringRef cmd
, bool force
) {
1354 auto pos
= m_command_dict
.find(std::string(cmd
));
1355 if (pos
!= m_command_dict
.end()) {
1356 if (force
|| pos
->second
->IsRemovable()) {
1357 // Only regular expression objects or python commands are removable under
1358 // normal circumstances.
1359 m_command_dict
.erase(pos
);
1366 bool CommandInterpreter::RemoveUser(llvm::StringRef user_name
) {
1367 CommandObject::CommandMap::iterator pos
=
1368 m_user_dict
.find(std::string(user_name
));
1369 if (pos
!= m_user_dict
.end()) {
1370 m_user_dict
.erase(pos
);
1376 bool CommandInterpreter::RemoveUserMultiword(llvm::StringRef multi_name
) {
1377 CommandObject::CommandMap::iterator pos
=
1378 m_user_mw_dict
.find(std::string(multi_name
));
1379 if (pos
!= m_user_mw_dict
.end()) {
1380 m_user_mw_dict
.erase(pos
);
1386 void CommandInterpreter::GetHelp(CommandReturnObject
&result
,
1387 uint32_t cmd_types
) {
1388 llvm::StringRef
help_prologue(GetDebugger().GetIOHandlerHelpPrologue());
1389 if (!help_prologue
.empty()) {
1390 OutputFormattedHelpText(result
.GetOutputStream(), llvm::StringRef(),
1394 CommandObject::CommandMap::const_iterator pos
;
1395 size_t max_len
= FindLongestCommandWord(m_command_dict
);
1397 if ((cmd_types
& eCommandTypesBuiltin
) == eCommandTypesBuiltin
) {
1398 result
.AppendMessage("Debugger commands:");
1399 result
.AppendMessage("");
1401 for (pos
= m_command_dict
.begin(); pos
!= m_command_dict
.end(); ++pos
) {
1402 if (!(cmd_types
& eCommandTypesHidden
) &&
1403 (pos
->first
.compare(0, 1, "_") == 0))
1406 OutputFormattedHelpText(result
.GetOutputStream(), pos
->first
, "--",
1407 pos
->second
->GetHelp(), max_len
);
1409 result
.AppendMessage("");
1412 if (!m_alias_dict
.empty() &&
1413 ((cmd_types
& eCommandTypesAliases
) == eCommandTypesAliases
)) {
1414 result
.AppendMessageWithFormat(
1415 "Current command abbreviations "
1416 "(type '%shelp command alias' for more info):\n",
1417 GetCommandPrefix());
1418 result
.AppendMessage("");
1419 max_len
= FindLongestCommandWord(m_alias_dict
);
1421 for (auto alias_pos
= m_alias_dict
.begin(); alias_pos
!= m_alias_dict
.end();
1423 OutputFormattedHelpText(result
.GetOutputStream(), alias_pos
->first
, "--",
1424 alias_pos
->second
->GetHelp(), max_len
);
1426 result
.AppendMessage("");
1429 if (!m_user_dict
.empty() &&
1430 ((cmd_types
& eCommandTypesUserDef
) == eCommandTypesUserDef
)) {
1431 result
.AppendMessage("Current user-defined commands:");
1432 result
.AppendMessage("");
1433 max_len
= FindLongestCommandWord(m_user_dict
);
1434 for (pos
= m_user_dict
.begin(); pos
!= m_user_dict
.end(); ++pos
) {
1435 OutputFormattedHelpText(result
.GetOutputStream(), pos
->first
, "--",
1436 pos
->second
->GetHelp(), max_len
);
1438 result
.AppendMessage("");
1441 if (!m_user_mw_dict
.empty() &&
1442 ((cmd_types
& eCommandTypesUserMW
) == eCommandTypesUserMW
)) {
1443 result
.AppendMessage("Current user-defined container commands:");
1444 result
.AppendMessage("");
1445 max_len
= FindLongestCommandWord(m_user_mw_dict
);
1446 for (pos
= m_user_mw_dict
.begin(); pos
!= m_user_mw_dict
.end(); ++pos
) {
1447 OutputFormattedHelpText(result
.GetOutputStream(), pos
->first
, "--",
1448 pos
->second
->GetHelp(), max_len
);
1450 result
.AppendMessage("");
1453 result
.AppendMessageWithFormat(
1454 "For more information on any command, type '%shelp <command-name>'.\n",
1455 GetCommandPrefix());
1458 CommandObject
*CommandInterpreter::GetCommandObjectForCommand(
1459 llvm::StringRef
&command_string
) {
1460 // This function finds the final, lowest-level, alias-resolved command object
1461 // whose 'Execute' function will eventually be invoked by the given command
1464 CommandObject
*cmd_obj
= nullptr;
1465 size_t start
= command_string
.find_first_not_of(k_white_space
);
1469 if (start
!= std::string::npos
) {
1470 // Get the next word from command_string.
1471 end
= command_string
.find_first_of(k_white_space
, start
);
1472 if (end
== std::string::npos
)
1473 end
= command_string
.size();
1474 std::string cmd_word
=
1475 std::string(command_string
.substr(start
, end
- start
));
1477 if (cmd_obj
== nullptr)
1478 // Since cmd_obj is NULL we are on our first time through this loop.
1479 // Check to see if cmd_word is a valid command or alias.
1480 cmd_obj
= GetCommandObject(cmd_word
);
1481 else if (cmd_obj
->IsMultiwordObject()) {
1482 // Our current object is a multi-word object; see if the cmd_word is a
1483 // valid sub-command for our object.
1484 CommandObject
*sub_cmd_obj
=
1485 cmd_obj
->GetSubcommandObject(cmd_word
.c_str());
1487 cmd_obj
= sub_cmd_obj
;
1488 else // cmd_word was not a valid sub-command word, so we are done
1491 // We have a cmd_obj and it is not a multi-word object, so we are done.
1494 // If we didn't find a valid command object, or our command object is not
1495 // a multi-word object, or we are at the end of the command_string, then
1496 // we are done. Otherwise, find the start of the next word.
1498 if (!cmd_obj
|| !cmd_obj
->IsMultiwordObject() ||
1499 end
>= command_string
.size())
1502 start
= command_string
.find_first_not_of(k_white_space
, end
);
1504 // Unable to find any more words.
1508 command_string
= command_string
.substr(end
);
1512 static const char *k_valid_command_chars
=
1513 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
1514 static void StripLeadingSpaces(std::string
&s
) {
1516 size_t pos
= s
.find_first_not_of(k_white_space
);
1517 if (pos
== std::string::npos
)
1525 static size_t FindArgumentTerminator(const std::string
&s
) {
1526 const size_t s_len
= s
.size();
1528 while (offset
< s_len
) {
1529 size_t pos
= s
.find("--", offset
);
1530 if (pos
== std::string::npos
)
1533 if (llvm::isSpace(s
[pos
- 1])) {
1534 // Check if the string ends "\s--" (where \s is a space character) or
1535 // if we have "\s--\s".
1536 if ((pos
+ 2 >= s_len
) || llvm::isSpace(s
[pos
+ 2])) {
1543 return std::string::npos
;
1546 static bool ExtractCommand(std::string
&command_string
, std::string
&command
,
1547 std::string
&suffix
, char "e_char
) {
1550 StripLeadingSpaces(command_string
);
1552 bool result
= false;
1555 if (!command_string
.empty()) {
1556 const char first_char
= command_string
[0];
1557 if (first_char
== '\'' || first_char
== '"') {
1558 quote_char
= first_char
;
1559 const size_t end_quote_pos
= command_string
.find(quote_char
, 1);
1560 if (end_quote_pos
== std::string::npos
) {
1561 command
.swap(command_string
);
1562 command_string
.erase();
1564 command
.assign(command_string
, 1, end_quote_pos
- 1);
1565 if (end_quote_pos
+ 1 < command_string
.size())
1566 command_string
.erase(0, command_string
.find_first_not_of(
1567 k_white_space
, end_quote_pos
+ 1));
1569 command_string
.erase();
1572 const size_t first_space_pos
=
1573 command_string
.find_first_of(k_white_space
);
1574 if (first_space_pos
== std::string::npos
) {
1575 command
.swap(command_string
);
1576 command_string
.erase();
1578 command
.assign(command_string
, 0, first_space_pos
);
1579 command_string
.erase(0, command_string
.find_first_not_of(
1580 k_white_space
, first_space_pos
));
1586 if (!command
.empty()) {
1587 // actual commands can't start with '-' or '_'
1588 if (command
[0] != '-' && command
[0] != '_') {
1589 size_t pos
= command
.find_first_not_of(k_valid_command_chars
);
1590 if (pos
> 0 && pos
!= std::string::npos
) {
1591 suffix
.assign(command
.begin() + pos
, command
.end());
1600 CommandObject
*CommandInterpreter::BuildAliasResult(
1601 llvm::StringRef alias_name
, std::string
&raw_input_string
,
1602 std::string
&alias_result
, CommandReturnObject
&result
) {
1603 CommandObject
*alias_cmd_obj
= nullptr;
1604 Args
cmd_args(raw_input_string
);
1605 alias_cmd_obj
= GetCommandObject(alias_name
);
1606 StreamString result_str
;
1608 if (!alias_cmd_obj
|| !alias_cmd_obj
->IsAlias()) {
1609 alias_result
.clear();
1610 return alias_cmd_obj
;
1612 std::pair
<CommandObjectSP
, OptionArgVectorSP
> desugared
=
1613 ((CommandAlias
*)alias_cmd_obj
)->Desugar();
1614 OptionArgVectorSP option_arg_vector_sp
= desugared
.second
;
1615 alias_cmd_obj
= desugared
.first
.get();
1616 std::string alias_name_str
= std::string(alias_name
);
1617 if ((cmd_args
.GetArgumentCount() == 0) ||
1618 (alias_name_str
!= cmd_args
.GetArgumentAtIndex(0)))
1619 cmd_args
.Unshift(alias_name_str
);
1621 result_str
.Printf("%s", alias_cmd_obj
->GetCommandName().str().c_str());
1623 if (!option_arg_vector_sp
.get()) {
1624 alias_result
= std::string(result_str
.GetString());
1625 return alias_cmd_obj
;
1627 OptionArgVector
*option_arg_vector
= option_arg_vector_sp
.get();
1632 for (const auto &entry
: *option_arg_vector
) {
1633 std::tie(option
, value_type
, value
) = entry
;
1634 if (option
== g_argument
) {
1635 result_str
.Printf(" %s", value
.c_str());
1639 result_str
.Printf(" %s", option
.c_str());
1640 if (value_type
== OptionParser::eNoArgument
)
1643 if (value_type
!= OptionParser::eOptionalArgument
)
1644 result_str
.Printf(" ");
1645 int index
= GetOptionArgumentPosition(value
.c_str());
1647 result_str
.Printf("%s", value
.c_str());
1648 else if (static_cast<size_t>(index
) >= cmd_args
.GetArgumentCount()) {
1650 result
.AppendErrorWithFormat("Not enough arguments provided; you "
1651 "need at least %d arguments to use "
1656 const Args::ArgEntry
&entry
= cmd_args
[index
];
1657 size_t strpos
= raw_input_string
.find(entry
.c_str());
1658 const char quote_char
= entry
.GetQuoteChar();
1659 if (strpos
!= std::string::npos
) {
1660 const size_t start_fudge
= quote_char
== '\0' ? 0 : 1;
1661 const size_t len_fudge
= quote_char
== '\0' ? 0 : 2;
1663 // Make sure we aren't going outside the bounds of the cmd string:
1664 if (strpos
< start_fudge
) {
1665 result
.AppendError("Unmatched quote at command beginning.");
1668 llvm::StringRef arg_text
= entry
.ref();
1669 if (strpos
- start_fudge
+ arg_text
.size() + len_fudge
>
1670 raw_input_string
.size()) {
1671 result
.AppendError("Unmatched quote at command end.");
1674 raw_input_string
= raw_input_string
.erase(
1675 strpos
- start_fudge
,
1676 strlen(cmd_args
.GetArgumentAtIndex(index
)) + len_fudge
);
1678 if (quote_char
== '\0')
1679 result_str
.Printf("%s", cmd_args
.GetArgumentAtIndex(index
));
1681 result_str
.Printf("%c%s%c", quote_char
, entry
.c_str(), quote_char
);
1685 alias_result
= std::string(result_str
.GetString());
1686 return alias_cmd_obj
;
1689 Status
CommandInterpreter::PreprocessCommand(std::string
&command
) {
1690 // The command preprocessor needs to do things to the command line before any
1691 // parsing of arguments or anything else is done. The only current stuff that
1692 // gets preprocessed is anything enclosed in backtick ('`') characters is
1693 // evaluated as an expression and the result of the expression must be a
1694 // scalar that can be substituted into the command. An example would be:
1695 // (lldb) memory read `$rsp + 20`
1696 Status error
; // Status for any expressions that might not evaluate
1697 size_t start_backtick
;
1699 while ((start_backtick
= command
.find('`', pos
)) != std::string::npos
) {
1700 // Stop if an error was encountered during the previous iteration.
1704 if (start_backtick
> 0 && command
[start_backtick
- 1] == '\\') {
1705 // The backtick was preceded by a '\' character, remove the slash and
1706 // don't treat the backtick as the start of an expression.
1707 command
.erase(start_backtick
- 1, 1);
1708 // No need to add one to start_backtick since we just deleted a char.
1709 pos
= start_backtick
;
1713 const size_t expr_content_start
= start_backtick
+ 1;
1714 const size_t end_backtick
= command
.find('`', expr_content_start
);
1716 if (end_backtick
== std::string::npos
) {
1717 // Stop if there's no end backtick.
1721 if (end_backtick
== expr_content_start
) {
1722 // Skip over empty expression. (two backticks in a row)
1723 command
.erase(start_backtick
, 2);
1727 std::string
expr_str(command
, expr_content_start
,
1728 end_backtick
- expr_content_start
);
1729 error
= PreprocessToken(expr_str
);
1730 // We always stop at the first error:
1734 command
.erase(start_backtick
, end_backtick
- start_backtick
+ 1);
1735 command
.insert(start_backtick
, std::string(expr_str
));
1736 pos
= start_backtick
+ expr_str
.size();
1742 CommandInterpreter::PreprocessToken(std::string
&expr_str
) {
1744 ExecutionContext
exe_ctx(GetExecutionContext());
1746 // Get a dummy target to allow for calculator mode while processing
1747 // backticks. This also helps break the infinite loop caused when target is
1749 Target
*exe_target
= exe_ctx
.GetTargetPtr();
1750 Target
&target
= exe_target
? *exe_target
: m_debugger
.GetDummyTarget();
1752 ValueObjectSP expr_result_valobj_sp
;
1754 EvaluateExpressionOptions options
;
1755 options
.SetCoerceToId(false);
1756 options
.SetUnwindOnError(true);
1757 options
.SetIgnoreBreakpoints(true);
1758 options
.SetKeepInMemory(false);
1759 options
.SetTryAllThreads(true);
1760 options
.SetTimeout(std::nullopt
);
1762 ExpressionResults expr_result
=
1763 target
.EvaluateExpression(expr_str
.c_str(), exe_ctx
.GetFramePtr(),
1764 expr_result_valobj_sp
, options
);
1766 if (expr_result
== eExpressionCompleted
) {
1768 if (expr_result_valobj_sp
)
1769 expr_result_valobj_sp
=
1770 expr_result_valobj_sp
->GetQualifiedRepresentationIfAvailable(
1771 expr_result_valobj_sp
->GetDynamicValueType(), true);
1772 if (expr_result_valobj_sp
->ResolveValue(scalar
)) {
1774 StreamString value_strm
;
1775 const bool show_type
= false;
1776 scalar
.GetValue(value_strm
, show_type
);
1777 size_t value_string_size
= value_strm
.GetSize();
1778 if (value_string_size
) {
1779 expr_str
= value_strm
.GetData();
1781 error
.SetErrorStringWithFormat("expression value didn't result "
1782 "in a scalar value for the "
1787 error
.SetErrorStringWithFormat("expression value didn't result "
1788 "in a scalar value for the "
1795 // If we have an error from the expression evaluation it will be in the
1796 // ValueObject error, which won't be success and we will just report it.
1797 // But if for some reason we didn't get a value object at all, then we will
1798 // make up some helpful errors from the expression result.
1799 if (expr_result_valobj_sp
)
1800 error
= expr_result_valobj_sp
->GetError();
1802 if (error
.Success()) {
1803 switch (expr_result
) {
1804 case eExpressionSetupError
:
1805 error
.SetErrorStringWithFormat(
1806 "expression setup error for the expression '%s'", expr_str
.c_str());
1808 case eExpressionParseError
:
1809 error
.SetErrorStringWithFormat(
1810 "expression parse error for the expression '%s'", expr_str
.c_str());
1812 case eExpressionResultUnavailable
:
1813 error
.SetErrorStringWithFormat(
1814 "expression error fetching result for the expression '%s'",
1817 case eExpressionCompleted
:
1819 case eExpressionDiscarded
:
1820 error
.SetErrorStringWithFormat(
1821 "expression discarded for the expression '%s'", expr_str
.c_str());
1823 case eExpressionInterrupted
:
1824 error
.SetErrorStringWithFormat(
1825 "expression interrupted for the expression '%s'", expr_str
.c_str());
1827 case eExpressionHitBreakpoint
:
1828 error
.SetErrorStringWithFormat(
1829 "expression hit breakpoint for the expression '%s'",
1832 case eExpressionTimedOut
:
1833 error
.SetErrorStringWithFormat(
1834 "expression timed out for the expression '%s'", expr_str
.c_str());
1836 case eExpressionStoppedForDebug
:
1837 error
.SetErrorStringWithFormat("expression stop at entry point "
1838 "for debugging for the "
1842 case eExpressionThreadVanished
:
1843 error
.SetErrorStringWithFormat(
1844 "expression thread vanished for the expression '%s'",
1852 bool CommandInterpreter::HandleCommand(const char *command_line
,
1853 LazyBool lazy_add_to_history
,
1854 const ExecutionContext
&override_context
,
1855 CommandReturnObject
&result
) {
1857 OverrideExecutionContext(override_context
);
1858 bool status
= HandleCommand(command_line
, lazy_add_to_history
, result
);
1859 RestoreExecutionContext();
1863 bool CommandInterpreter::HandleCommand(const char *command_line
,
1864 LazyBool lazy_add_to_history
,
1865 CommandReturnObject
&result
,
1866 bool force_repeat_command
) {
1867 std::string
command_string(command_line
);
1868 std::string
original_command_string(command_line
);
1870 Log
*log
= GetLog(LLDBLog::Commands
);
1871 llvm::PrettyStackTraceFormat
stack_trace("HandleCommand(command = \"%s\")",
1874 LLDB_LOGF(log
, "Processing command: %s", command_line
);
1875 LLDB_SCOPED_TIMERF("Processing command: %s.", command_line
);
1877 if (INTERRUPT_REQUESTED(GetDebugger(), "Interrupted initiating command")) {
1878 result
.AppendError("... Interrupted");
1882 bool add_to_history
;
1883 if (lazy_add_to_history
== eLazyBoolCalculate
)
1884 add_to_history
= (m_command_source_depth
== 0);
1886 add_to_history
= (lazy_add_to_history
== eLazyBoolYes
);
1888 m_transcript_stream
<< "(lldb) " << command_line
<< '\n';
1890 bool empty_command
= false;
1891 bool comment_command
= false;
1892 if (command_string
.empty())
1893 empty_command
= true;
1895 const char *k_space_characters
= "\t\n\v\f\r ";
1897 size_t non_space
= command_string
.find_first_not_of(k_space_characters
);
1898 // Check for empty line or comment line (lines whose first non-space
1899 // character is the comment character for this interpreter)
1900 if (non_space
== std::string::npos
)
1901 empty_command
= true;
1902 else if (command_string
[non_space
] == m_comment_char
)
1903 comment_command
= true;
1904 else if (command_string
[non_space
] == CommandHistory::g_repeat_char
) {
1905 llvm::StringRef
search_str(command_string
);
1906 search_str
= search_str
.drop_front(non_space
);
1907 if (auto hist_str
= m_command_history
.FindString(search_str
)) {
1908 add_to_history
= false;
1909 command_string
= std::string(*hist_str
);
1910 original_command_string
= std::string(*hist_str
);
1912 result
.AppendErrorWithFormat("Could not find entry: %s in history",
1913 command_string
.c_str());
1919 if (empty_command
) {
1920 if (!GetRepeatPreviousCommand()) {
1921 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
1925 if (m_command_history
.IsEmpty()) {
1926 result
.AppendError("empty command");
1930 command_line
= m_repeat_command
.c_str();
1931 command_string
= command_line
;
1932 original_command_string
= command_line
;
1933 if (m_repeat_command
.empty()) {
1934 result
.AppendError("No auto repeat.");
1938 add_to_history
= false;
1939 } else if (comment_command
) {
1940 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
1946 // Before we do ANY kind of argument processing, we need to figure out what
1947 // the real/final command object is for the specified command. This gets
1948 // complicated by the fact that the user could have specified an alias, and,
1949 // in translating the alias, there may also be command options and/or even
1950 // data (including raw text strings) that need to be found and inserted into
1951 // the command line as part of the translation. So this first step is plain
1952 // look-up and replacement, resulting in:
1953 // 1. the command object whose Execute method will actually be called
1954 // 2. a revised command string, with all substitutions and replacements
1956 // From 1 above, we can determine whether the Execute function wants raw
1959 CommandObject
*cmd_obj
= ResolveCommandImpl(command_string
, result
);
1961 // We have to preprocess the whole command string for Raw commands, since we
1962 // don't know the structure of the command. For parsed commands, we only
1963 // treat backticks as quote characters specially.
1964 // FIXME: We probably want to have raw commands do their own preprocessing.
1965 // For instance, I don't think people expect substitution in expr expressions.
1966 if (cmd_obj
&& cmd_obj
->WantsRawCommandString()) {
1967 Status
error(PreprocessCommand(command_string
));
1970 result
.AppendError(error
.AsCString());
1975 // Although the user may have abbreviated the command, the command_string now
1976 // has the command expanded to the full name. For example, if the input was
1977 // "br s -n main", command_string is now "breakpoint set -n main".
1979 llvm::StringRef command_name
= cmd_obj
? cmd_obj
->GetCommandName() : "<not found>";
1980 LLDB_LOGF(log
, "HandleCommand, cmd_obj : '%s'", command_name
.str().c_str());
1981 LLDB_LOGF(log
, "HandleCommand, (revised) command_string: '%s'",
1982 command_string
.c_str());
1983 const bool wants_raw_input
=
1984 (cmd_obj
!= nullptr) ? cmd_obj
->WantsRawCommandString() : false;
1985 LLDB_LOGF(log
, "HandleCommand, wants_raw_input:'%s'",
1986 wants_raw_input
? "True" : "False");
1990 // Take care of things like setting up the history command & calling the
1991 // appropriate Execute method on the CommandObject, with the appropriate
1994 if (cmd_obj
!= nullptr) {
1995 bool generate_repeat_command
= add_to_history
;
1996 // If we got here when empty_command was true, then this command is a
1997 // stored "repeat command" which we should give a chance to produce it's
1998 // repeat command, even though we don't add repeat commands to the history.
1999 generate_repeat_command
|= empty_command
;
2000 // For `command regex`, the regex command (ex `bt`) is added to history, but
2001 // the resolved command (ex `thread backtrace`) is _not_ added to history.
2002 // However, the resolved command must be given the opportunity to provide a
2003 // repeat command. `force_repeat_command` supports this case.
2004 generate_repeat_command
|= force_repeat_command
;
2005 if (generate_repeat_command
) {
2006 Args
command_args(command_string
);
2007 std::optional
<std::string
> repeat_command
=
2008 cmd_obj
->GetRepeatCommand(command_args
, 0);
2009 if (repeat_command
) {
2010 LLDB_LOGF(log
, "Repeat command: %s", repeat_command
->data());
2011 m_repeat_command
.assign(*repeat_command
);
2013 m_repeat_command
.assign(original_command_string
);
2018 m_command_history
.AppendString(original_command_string
);
2020 std::string remainder
;
2021 const std::size_t actual_cmd_name_len
= cmd_obj
->GetCommandName().size();
2022 if (actual_cmd_name_len
< command_string
.length())
2023 remainder
= command_string
.substr(actual_cmd_name_len
);
2025 // Remove any initial spaces
2026 size_t pos
= remainder
.find_first_not_of(k_white_space
);
2027 if (pos
!= 0 && pos
!= std::string::npos
)
2028 remainder
.erase(0, pos
);
2031 log
, "HandleCommand, command line after removing command name(s): '%s'",
2034 cmd_obj
->Execute(remainder
.c_str(), result
);
2037 LLDB_LOGF(log
, "HandleCommand, command %s",
2038 (result
.Succeeded() ? "succeeded" : "did not succeed"));
2040 m_transcript_stream
<< result
.GetOutputData();
2041 m_transcript_stream
<< result
.GetErrorData();
2043 return result
.Succeeded();
2046 void CommandInterpreter::HandleCompletionMatches(CompletionRequest
&request
) {
2047 bool look_for_subcommand
= false;
2049 // For any of the command completions a unique match will be a complete word.
2051 if (request
.GetParsedLine().GetArgumentCount() == 0) {
2052 // We got nothing on the command line, so return the list of commands
2053 bool include_aliases
= true;
2054 StringList new_matches
, descriptions
;
2055 GetCommandNamesMatchingPartialString("", include_aliases
, new_matches
,
2057 request
.AddCompletions(new_matches
, descriptions
);
2058 } else if (request
.GetCursorIndex() == 0) {
2059 // The cursor is in the first argument, so just do a lookup in the
2061 StringList new_matches
, new_descriptions
;
2062 CommandObject
*cmd_obj
=
2063 GetCommandObject(request
.GetParsedLine().GetArgumentAtIndex(0),
2064 &new_matches
, &new_descriptions
);
2066 if (new_matches
.GetSize() && cmd_obj
&& cmd_obj
->IsMultiwordObject() &&
2067 new_matches
.GetStringAtIndex(0) != nullptr &&
2068 strcmp(request
.GetParsedLine().GetArgumentAtIndex(0),
2069 new_matches
.GetStringAtIndex(0)) == 0) {
2070 if (request
.GetParsedLine().GetArgumentCount() != 1) {
2071 look_for_subcommand
= true;
2072 new_matches
.DeleteStringAtIndex(0);
2073 new_descriptions
.DeleteStringAtIndex(0);
2074 request
.AppendEmptyArgument();
2077 request
.AddCompletions(new_matches
, new_descriptions
);
2080 if (request
.GetCursorIndex() > 0 || look_for_subcommand
) {
2081 // We are completing further on into a commands arguments, so find the
2082 // command and tell it to complete the command. First see if there is a
2083 // matching initial command:
2084 CommandObject
*command_object
=
2085 GetCommandObject(request
.GetParsedLine().GetArgumentAtIndex(0));
2086 if (command_object
) {
2087 request
.ShiftArguments();
2088 command_object
->HandleCompletion(request
);
2093 void CommandInterpreter::HandleCompletion(CompletionRequest
&request
) {
2095 // Don't complete comments, and if the line we are completing is just the
2096 // history repeat character, substitute the appropriate history line.
2097 llvm::StringRef first_arg
= request
.GetParsedLine().GetArgumentAtIndex(0);
2099 if (!first_arg
.empty()) {
2100 if (first_arg
.front() == m_comment_char
)
2102 if (first_arg
.front() == CommandHistory::g_repeat_char
) {
2103 if (auto hist_str
= m_command_history
.FindString(first_arg
))
2104 request
.AddCompletion(*hist_str
, "Previous command history event",
2105 CompletionMode::RewriteLine
);
2110 HandleCompletionMatches(request
);
2113 std::optional
<std::string
>
2114 CommandInterpreter::GetAutoSuggestionForCommand(llvm::StringRef line
) {
2116 return std::nullopt
;
2117 const size_t s
= m_command_history
.GetSize();
2118 for (int i
= s
- 1; i
>= 0; --i
) {
2119 llvm::StringRef entry
= m_command_history
.GetStringAtIndex(i
);
2120 if (entry
.consume_front(line
))
2123 return std::nullopt
;
2126 void CommandInterpreter::UpdatePrompt(llvm::StringRef new_prompt
) {
2127 EventSP
prompt_change_event_sp(
2128 new Event(eBroadcastBitResetPrompt
, new EventDataBytes(new_prompt
)));
2130 BroadcastEvent(prompt_change_event_sp
);
2131 if (m_command_io_handler_sp
)
2132 m_command_io_handler_sp
->SetPrompt(new_prompt
);
2135 bool CommandInterpreter::Confirm(llvm::StringRef message
, bool default_answer
) {
2136 // Check AutoConfirm first:
2137 if (m_debugger
.GetAutoConfirm())
2138 return default_answer
;
2140 IOHandlerConfirm
*confirm
=
2141 new IOHandlerConfirm(m_debugger
, message
, default_answer
);
2142 IOHandlerSP
io_handler_sp(confirm
);
2143 m_debugger
.RunIOHandlerSync(io_handler_sp
);
2144 return confirm
->GetResponse();
2147 const CommandAlias
*
2148 CommandInterpreter::GetAlias(llvm::StringRef alias_name
) const {
2149 OptionArgVectorSP ret_val
;
2151 auto pos
= m_alias_dict
.find(std::string(alias_name
));
2152 if (pos
!= m_alias_dict
.end())
2153 return (CommandAlias
*)pos
->second
.get();
2158 bool CommandInterpreter::HasCommands() const { return (!m_command_dict
.empty()); }
2160 bool CommandInterpreter::HasAliases() const { return (!m_alias_dict
.empty()); }
2162 bool CommandInterpreter::HasUserCommands() const { return (!m_user_dict
.empty()); }
2164 bool CommandInterpreter::HasUserMultiwordCommands() const {
2165 return (!m_user_mw_dict
.empty());
2168 bool CommandInterpreter::HasAliasOptions() const { return HasAliases(); }
2170 void CommandInterpreter::BuildAliasCommandArgs(CommandObject
*alias_cmd_obj
,
2171 const char *alias_name
,
2173 std::string
&raw_input_string
,
2174 CommandReturnObject
&result
) {
2175 OptionArgVectorSP option_arg_vector_sp
=
2176 GetAlias(alias_name
)->GetOptionArguments();
2178 bool wants_raw_input
= alias_cmd_obj
->WantsRawCommandString();
2180 // Make sure that the alias name is the 0th element in cmd_args
2181 std::string alias_name_str
= alias_name
;
2182 if (alias_name_str
!= cmd_args
.GetArgumentAtIndex(0))
2183 cmd_args
.Unshift(alias_name_str
);
2185 Args
new_args(alias_cmd_obj
->GetCommandName());
2186 if (new_args
.GetArgumentCount() == 2)
2189 if (option_arg_vector_sp
.get()) {
2190 if (wants_raw_input
) {
2191 // We have a command that both has command options and takes raw input.
2192 // Make *sure* it has a " -- " in the right place in the
2193 // raw_input_string.
2194 size_t pos
= raw_input_string
.find(" -- ");
2195 if (pos
== std::string::npos
) {
2196 // None found; assume it goes at the beginning of the raw input string
2197 raw_input_string
.insert(0, " -- ");
2201 OptionArgVector
*option_arg_vector
= option_arg_vector_sp
.get();
2202 const size_t old_size
= cmd_args
.GetArgumentCount();
2203 std::vector
<bool> used(old_size
+ 1, false);
2210 for (const auto &option_entry
: *option_arg_vector
) {
2211 std::tie(option
, value_type
, value
) = option_entry
;
2212 if (option
== g_argument
) {
2213 if (!wants_raw_input
|| (value
!= "--")) {
2214 // Since we inserted this above, make sure we don't insert it twice
2215 new_args
.AppendArgument(value
);
2220 if (value_type
!= OptionParser::eOptionalArgument
)
2221 new_args
.AppendArgument(option
);
2223 if (value
== g_no_argument
)
2226 int index
= GetOptionArgumentPosition(value
.c_str());
2228 // value was NOT a positional argument; must be a real value
2229 if (value_type
!= OptionParser::eOptionalArgument
)
2230 new_args
.AppendArgument(value
);
2232 new_args
.AppendArgument(option
+ value
);
2235 } else if (static_cast<size_t>(index
) >= cmd_args
.GetArgumentCount()) {
2236 result
.AppendErrorWithFormat("Not enough arguments provided; you "
2237 "need at least %d arguments to use "
2242 // Find and remove cmd_args.GetArgumentAtIndex(i) from raw_input_string
2244 raw_input_string
.find(cmd_args
.GetArgumentAtIndex(index
));
2245 if (strpos
!= std::string::npos
) {
2246 raw_input_string
= raw_input_string
.erase(
2247 strpos
, strlen(cmd_args
.GetArgumentAtIndex(index
)));
2250 if (value_type
!= OptionParser::eOptionalArgument
)
2251 new_args
.AppendArgument(cmd_args
.GetArgumentAtIndex(index
));
2253 new_args
.AppendArgument(option
+ cmd_args
.GetArgumentAtIndex(index
));
2259 for (auto entry
: llvm::enumerate(cmd_args
.entries())) {
2260 if (!used
[entry
.index()] && !wants_raw_input
)
2261 new_args
.AppendArgument(entry
.value().ref());
2265 cmd_args
.SetArguments(new_args
.GetArgumentCount(),
2266 new_args
.GetConstArgumentVector());
2268 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
2269 // This alias was not created with any options; nothing further needs to be
2270 // done, unless it is a command that wants raw input, in which case we need
2271 // to clear the rest of the data from cmd_args, since its in the raw input
2273 if (wants_raw_input
) {
2275 cmd_args
.SetArguments(new_args
.GetArgumentCount(),
2276 new_args
.GetConstArgumentVector());
2281 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
2284 int CommandInterpreter::GetOptionArgumentPosition(const char *in_string
) {
2285 int position
= 0; // Any string that isn't an argument position, i.e. '%'
2286 // followed by an integer, gets a position
2289 const char *cptr
= in_string
;
2291 // Does it start with '%'
2292 if (cptr
[0] == '%') {
2295 // Is the rest of it entirely digits?
2296 if (isdigit(cptr
[0])) {
2297 const char *start
= cptr
;
2298 while (isdigit(cptr
[0]))
2301 // We've gotten to the end of the digits; are we at the end of the
2303 if (cptr
[0] == '\0')
2304 position
= atoi(start
);
2311 static void GetHomeInitFile(llvm::SmallVectorImpl
<char> &init_file
,
2312 llvm::StringRef suffix
= {}) {
2313 std::string init_file_name
= ".lldbinit";
2314 if (!suffix
.empty()) {
2315 init_file_name
.append("-");
2316 init_file_name
.append(suffix
.str());
2319 FileSystem::Instance().GetHomeDirectory(init_file
);
2320 llvm::sys::path::append(init_file
, init_file_name
);
2322 FileSystem::Instance().Resolve(init_file
);
2325 static void GetHomeREPLInitFile(llvm::SmallVectorImpl
<char> &init_file
,
2326 LanguageType language
) {
2327 if (language
== eLanguageTypeUnknown
) {
2328 LanguageSet repl_languages
= Language::GetLanguagesSupportingREPLs();
2329 if (auto main_repl_language
= repl_languages
.GetSingularLanguage())
2330 language
= *main_repl_language
;
2335 std::string init_file_name
=
2336 (llvm::Twine(".lldbinit-") +
2337 llvm::Twine(Language::GetNameForLanguageType(language
)) +
2338 llvm::Twine("-repl"))
2340 FileSystem::Instance().GetHomeDirectory(init_file
);
2341 llvm::sys::path::append(init_file
, init_file_name
);
2342 FileSystem::Instance().Resolve(init_file
);
2345 static void GetCwdInitFile(llvm::SmallVectorImpl
<char> &init_file
) {
2346 llvm::StringRef s
= ".lldbinit";
2347 init_file
.assign(s
.begin(), s
.end());
2348 FileSystem::Instance().Resolve(init_file
);
2351 void CommandInterpreter::SourceInitFile(FileSpec file
,
2352 CommandReturnObject
&result
) {
2353 assert(!m_skip_lldbinit_files
);
2355 if (!FileSystem::Instance().Exists(file
)) {
2356 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
2360 // Use HandleCommand to 'source' the given file; this will do the actual
2361 // broadcasting of the commands back to any appropriate listener (see
2362 // CommandObjectSource::Execute for more details).
2363 const bool saved_batch
= SetBatchCommandMode(true);
2364 CommandInterpreterRunOptions options
;
2365 options
.SetSilent(true);
2366 options
.SetPrintErrors(true);
2367 options
.SetStopOnError(false);
2368 options
.SetStopOnContinue(true);
2369 HandleCommandsFromFile(file
, options
, result
);
2370 SetBatchCommandMode(saved_batch
);
2373 void CommandInterpreter::SourceInitFileCwd(CommandReturnObject
&result
) {
2374 if (m_skip_lldbinit_files
) {
2375 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
2379 llvm::SmallString
<128> init_file
;
2380 GetCwdInitFile(init_file
);
2381 if (!FileSystem::Instance().Exists(init_file
)) {
2382 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
2386 LoadCWDlldbinitFile should_load
=
2387 Target::GetGlobalProperties().GetLoadCWDlldbinitFile();
2389 switch (should_load
) {
2390 case eLoadCWDlldbinitFalse
:
2391 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
2393 case eLoadCWDlldbinitTrue
:
2394 SourceInitFile(FileSpec(init_file
.str()), result
);
2396 case eLoadCWDlldbinitWarn
: {
2397 llvm::SmallString
<128> home_init_file
;
2398 GetHomeInitFile(home_init_file
);
2399 if (llvm::sys::path::parent_path(init_file
) ==
2400 llvm::sys::path::parent_path(home_init_file
)) {
2401 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
2403 result
.AppendError(InitFileWarning
);
2409 /// We will first see if there is an application specific ".lldbinit" file
2410 /// whose name is "~/.lldbinit" followed by a "-" and the name of the program.
2411 /// If this file doesn't exist, we fall back to the REPL init file or the
2412 /// default home init file in "~/.lldbinit".
2413 void CommandInterpreter::SourceInitFileHome(CommandReturnObject
&result
,
2415 if (m_skip_lldbinit_files
) {
2416 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
2420 llvm::SmallString
<128> init_file
;
2423 GetHomeREPLInitFile(init_file
, GetDebugger().GetREPLLanguage());
2425 if (init_file
.empty())
2426 GetHomeInitFile(init_file
);
2428 if (!m_skip_app_init_files
) {
2429 llvm::StringRef program_name
=
2430 HostInfo::GetProgramFileSpec().GetFilename().GetStringRef();
2431 llvm::SmallString
<128> program_init_file
;
2432 GetHomeInitFile(program_init_file
, program_name
);
2433 if (FileSystem::Instance().Exists(program_init_file
))
2434 init_file
= program_init_file
;
2437 SourceInitFile(FileSpec(init_file
.str()), result
);
2440 void CommandInterpreter::SourceInitFileGlobal(CommandReturnObject
&result
) {
2441 #ifdef LLDB_GLOBAL_INIT_DIRECTORY
2442 if (!m_skip_lldbinit_files
) {
2443 FileSpec
init_file(LLDB_GLOBAL_INIT_DIRECTORY
);
2445 init_file
.MakeAbsolute(HostInfo::GetShlibDir());
2447 init_file
.AppendPathComponent("lldbinit");
2448 SourceInitFile(init_file
, result
);
2452 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
2455 const char *CommandInterpreter::GetCommandPrefix() {
2456 const char *prefix
= GetDebugger().GetIOHandlerCommandPrefix();
2457 return prefix
== nullptr ? "" : prefix
;
2460 PlatformSP
CommandInterpreter::GetPlatform(bool prefer_target_platform
) {
2461 PlatformSP platform_sp
;
2462 if (prefer_target_platform
) {
2463 ExecutionContext
exe_ctx(GetExecutionContext());
2464 Target
*target
= exe_ctx
.GetTargetPtr();
2466 platform_sp
= target
->GetPlatform();
2470 platform_sp
= m_debugger
.GetPlatformList().GetSelectedPlatform();
2474 bool CommandInterpreter::DidProcessStopAbnormally() const {
2475 auto exe_ctx
= GetExecutionContext();
2476 TargetSP target_sp
= exe_ctx
.GetTargetSP();
2480 ProcessSP
process_sp(target_sp
->GetProcessSP());
2484 if (eStateStopped
!= process_sp
->GetState())
2487 for (const auto &thread_sp
: process_sp
->GetThreadList().Threads()) {
2488 StopInfoSP stop_info
= thread_sp
->GetStopInfo();
2490 // If there's no stop_info, keep iterating through the other threads;
2491 // it's enough that any thread has got a stop_info that indicates
2492 // an abnormal stop, to consider the process to be stopped abnormally.
2496 const StopReason reason
= stop_info
->GetStopReason();
2497 if (reason
== eStopReasonException
||
2498 reason
== eStopReasonInstrumentation
||
2499 reason
== eStopReasonProcessorTrace
)
2502 if (reason
== eStopReasonSignal
) {
2503 const auto stop_signal
= static_cast<int32_t>(stop_info
->GetValue());
2504 UnixSignalsSP signals_sp
= process_sp
->GetUnixSignals();
2505 if (!signals_sp
|| !signals_sp
->SignalIsValid(stop_signal
))
2506 // The signal is unknown, treat it as abnormal.
2509 const auto sigint_num
= signals_sp
->GetSignalNumberFromName("SIGINT");
2510 const auto sigstop_num
= signals_sp
->GetSignalNumberFromName("SIGSTOP");
2511 if ((stop_signal
!= sigint_num
) && (stop_signal
!= sigstop_num
))
2512 // The signal very likely implies a crash.
2521 CommandInterpreter::HandleCommands(const StringList
&commands
,
2522 const ExecutionContext
&override_context
,
2523 const CommandInterpreterRunOptions
&options
,
2524 CommandReturnObject
&result
) {
2526 OverrideExecutionContext(override_context
);
2527 HandleCommands(commands
, options
, result
);
2528 RestoreExecutionContext();
2531 void CommandInterpreter::HandleCommands(const StringList
&commands
,
2532 const CommandInterpreterRunOptions
&options
,
2533 CommandReturnObject
&result
) {
2534 size_t num_lines
= commands
.GetSize();
2536 // If we are going to continue past a "continue" then we need to run the
2537 // commands synchronously. Make sure you reset this value anywhere you return
2538 // from the function.
2540 bool old_async_execution
= m_debugger
.GetAsyncExecution();
2542 if (!options
.GetStopOnContinue()) {
2543 m_debugger
.SetAsyncExecution(false);
2546 for (size_t idx
= 0; idx
< num_lines
; idx
++) {
2547 const char *cmd
= commands
.GetStringAtIndex(idx
);
2551 if (options
.GetEchoCommands()) {
2552 // TODO: Add Stream support.
2553 result
.AppendMessageWithFormat("%s %s\n",
2554 m_debugger
.GetPrompt().str().c_str(), cmd
);
2557 CommandReturnObject
tmp_result(m_debugger
.GetUseColor());
2558 tmp_result
.SetInteractive(result
.GetInteractive());
2559 tmp_result
.SetSuppressImmediateOutput(true);
2561 // We might call into a regex or alias command, in which case the
2562 // add_to_history will get lost. This m_command_source_depth dingus is the
2563 // way we turn off adding to the history in that case, so set it up here.
2564 if (!options
.GetAddToHistory())
2565 m_command_source_depth
++;
2566 bool success
= HandleCommand(cmd
, options
.m_add_to_history
, tmp_result
);
2567 if (!options
.GetAddToHistory())
2568 m_command_source_depth
--;
2570 if (options
.GetPrintResults()) {
2571 if (tmp_result
.Succeeded())
2572 result
.AppendMessage(tmp_result
.GetOutputData());
2575 if (!success
|| !tmp_result
.Succeeded()) {
2576 llvm::StringRef error_msg
= tmp_result
.GetErrorData();
2577 if (error_msg
.empty())
2578 error_msg
= "<unknown error>.\n";
2579 if (options
.GetStopOnError()) {
2580 result
.AppendErrorWithFormat(
2581 "Aborting reading of commands after command #%" PRIu64
2582 ": '%s' failed with %s",
2583 (uint64_t)idx
, cmd
, error_msg
.str().c_str());
2584 m_debugger
.SetAsyncExecution(old_async_execution
);
2586 } else if (options
.GetPrintResults()) {
2587 result
.AppendMessageWithFormat(
2588 "Command #%" PRIu64
" '%s' failed with %s", (uint64_t)idx
+ 1, cmd
,
2589 error_msg
.str().c_str());
2593 if (result
.GetImmediateOutputStream())
2594 result
.GetImmediateOutputStream()->Flush();
2596 if (result
.GetImmediateErrorStream())
2597 result
.GetImmediateErrorStream()->Flush();
2599 // N.B. Can't depend on DidChangeProcessState, because the state coming
2600 // into the command execution could be running (for instance in Breakpoint
2601 // Commands. So we check the return value to see if it is has running in
2603 if ((tmp_result
.GetStatus() == eReturnStatusSuccessContinuingNoResult
) ||
2604 (tmp_result
.GetStatus() == eReturnStatusSuccessContinuingResult
)) {
2605 if (options
.GetStopOnContinue()) {
2606 // If we caused the target to proceed, and we're going to stop in that
2607 // case, set the status in our real result before returning. This is
2608 // an error if the continue was not the last command in the set of
2609 // commands to be run.
2610 if (idx
!= num_lines
- 1)
2611 result
.AppendErrorWithFormat(
2612 "Aborting reading of commands after command #%" PRIu64
2613 ": '%s' continued the target.\n",
2614 (uint64_t)idx
+ 1, cmd
);
2616 result
.AppendMessageWithFormat("Command #%" PRIu64
2617 " '%s' continued the target.\n",
2618 (uint64_t)idx
+ 1, cmd
);
2620 result
.SetStatus(tmp_result
.GetStatus());
2621 m_debugger
.SetAsyncExecution(old_async_execution
);
2627 // Also check for "stop on crash here:
2628 if (tmp_result
.GetDidChangeProcessState() && options
.GetStopOnCrash() &&
2629 DidProcessStopAbnormally()) {
2630 if (idx
!= num_lines
- 1)
2631 result
.AppendErrorWithFormat(
2632 "Aborting reading of commands after command #%" PRIu64
2633 ": '%s' stopped with a signal or exception.\n",
2634 (uint64_t)idx
+ 1, cmd
);
2636 result
.AppendMessageWithFormat(
2637 "Command #%" PRIu64
" '%s' stopped with a signal or exception.\n",
2638 (uint64_t)idx
+ 1, cmd
);
2640 result
.SetStatus(tmp_result
.GetStatus());
2641 m_debugger
.SetAsyncExecution(old_async_execution
);
2647 result
.SetStatus(eReturnStatusSuccessFinishResult
);
2648 m_debugger
.SetAsyncExecution(old_async_execution
);
2651 // Make flags that we can pass into the IOHandler so our delegates can do the
2654 eHandleCommandFlagStopOnContinue
= (1u << 0),
2655 eHandleCommandFlagStopOnError
= (1u << 1),
2656 eHandleCommandFlagEchoCommand
= (1u << 2),
2657 eHandleCommandFlagEchoCommentCommand
= (1u << 3),
2658 eHandleCommandFlagPrintResult
= (1u << 4),
2659 eHandleCommandFlagPrintErrors
= (1u << 5),
2660 eHandleCommandFlagStopOnCrash
= (1u << 6)
2663 void CommandInterpreter::HandleCommandsFromFile(
2664 FileSpec
&cmd_file
, const ExecutionContext
&context
,
2665 const CommandInterpreterRunOptions
&options
, CommandReturnObject
&result
) {
2666 OverrideExecutionContext(context
);
2667 HandleCommandsFromFile(cmd_file
, options
, result
);
2668 RestoreExecutionContext();
2671 void CommandInterpreter::HandleCommandsFromFile(FileSpec
&cmd_file
,
2672 const CommandInterpreterRunOptions
&options
, CommandReturnObject
&result
) {
2673 if (!FileSystem::Instance().Exists(cmd_file
)) {
2674 result
.AppendErrorWithFormat(
2675 "Error reading commands from file %s - file not found.\n",
2676 cmd_file
.GetFilename().AsCString("<Unknown>"));
2680 std::string cmd_file_path
= cmd_file
.GetPath();
2681 auto input_file_up
=
2682 FileSystem::Instance().Open(cmd_file
, File::eOpenOptionReadOnly
);
2683 if (!input_file_up
) {
2684 std::string error
= llvm::toString(input_file_up
.takeError());
2685 result
.AppendErrorWithFormatv(
2686 "error: an error occurred read file '{0}': {1}\n", cmd_file_path
,
2687 llvm::fmt_consume(input_file_up
.takeError()));
2690 FileSP input_file_sp
= FileSP(std::move(input_file_up
.get()));
2692 Debugger
&debugger
= GetDebugger();
2696 if (options
.m_stop_on_continue
== eLazyBoolCalculate
) {
2697 if (m_command_source_flags
.empty()) {
2698 // Stop on continue by default
2699 flags
|= eHandleCommandFlagStopOnContinue
;
2700 } else if (m_command_source_flags
.back() &
2701 eHandleCommandFlagStopOnContinue
) {
2702 flags
|= eHandleCommandFlagStopOnContinue
;
2704 } else if (options
.m_stop_on_continue
== eLazyBoolYes
) {
2705 flags
|= eHandleCommandFlagStopOnContinue
;
2708 if (options
.m_stop_on_error
== eLazyBoolCalculate
) {
2709 if (m_command_source_flags
.empty()) {
2710 if (GetStopCmdSourceOnError())
2711 flags
|= eHandleCommandFlagStopOnError
;
2712 } else if (m_command_source_flags
.back() & eHandleCommandFlagStopOnError
) {
2713 flags
|= eHandleCommandFlagStopOnError
;
2715 } else if (options
.m_stop_on_error
== eLazyBoolYes
) {
2716 flags
|= eHandleCommandFlagStopOnError
;
2719 // stop-on-crash can only be set, if it is present in all levels of
2720 // pushed flag sets.
2721 if (options
.GetStopOnCrash()) {
2722 if (m_command_source_flags
.empty()) {
2723 flags
|= eHandleCommandFlagStopOnCrash
;
2724 } else if (m_command_source_flags
.back() & eHandleCommandFlagStopOnCrash
) {
2725 flags
|= eHandleCommandFlagStopOnCrash
;
2729 if (options
.m_echo_commands
== eLazyBoolCalculate
) {
2730 if (m_command_source_flags
.empty()) {
2731 // Echo command by default
2732 flags
|= eHandleCommandFlagEchoCommand
;
2733 } else if (m_command_source_flags
.back() & eHandleCommandFlagEchoCommand
) {
2734 flags
|= eHandleCommandFlagEchoCommand
;
2736 } else if (options
.m_echo_commands
== eLazyBoolYes
) {
2737 flags
|= eHandleCommandFlagEchoCommand
;
2740 // We will only ever ask for this flag, if we echo commands in general.
2741 if (options
.m_echo_comment_commands
== eLazyBoolCalculate
) {
2742 if (m_command_source_flags
.empty()) {
2743 // Echo comments by default
2744 flags
|= eHandleCommandFlagEchoCommentCommand
;
2745 } else if (m_command_source_flags
.back() &
2746 eHandleCommandFlagEchoCommentCommand
) {
2747 flags
|= eHandleCommandFlagEchoCommentCommand
;
2749 } else if (options
.m_echo_comment_commands
== eLazyBoolYes
) {
2750 flags
|= eHandleCommandFlagEchoCommentCommand
;
2753 if (options
.m_print_results
== eLazyBoolCalculate
) {
2754 if (m_command_source_flags
.empty()) {
2755 // Print output by default
2756 flags
|= eHandleCommandFlagPrintResult
;
2757 } else if (m_command_source_flags
.back() & eHandleCommandFlagPrintResult
) {
2758 flags
|= eHandleCommandFlagPrintResult
;
2760 } else if (options
.m_print_results
== eLazyBoolYes
) {
2761 flags
|= eHandleCommandFlagPrintResult
;
2764 if (options
.m_print_errors
== eLazyBoolCalculate
) {
2765 if (m_command_source_flags
.empty()) {
2766 // Print output by default
2767 flags
|= eHandleCommandFlagPrintErrors
;
2768 } else if (m_command_source_flags
.back() & eHandleCommandFlagPrintErrors
) {
2769 flags
|= eHandleCommandFlagPrintErrors
;
2771 } else if (options
.m_print_errors
== eLazyBoolYes
) {
2772 flags
|= eHandleCommandFlagPrintErrors
;
2775 if (flags
& eHandleCommandFlagPrintResult
) {
2776 debugger
.GetOutputFile().Printf("Executing commands in '%s'.\n",
2777 cmd_file_path
.c_str());
2780 // Used for inheriting the right settings when "command source" might
2781 // have nested "command source" commands
2782 lldb::StreamFileSP empty_stream_sp
;
2783 m_command_source_flags
.push_back(flags
);
2784 IOHandlerSP
io_handler_sp(new IOHandlerEditline(
2785 debugger
, IOHandler::Type::CommandInterpreter
, input_file_sp
,
2786 empty_stream_sp
, // Pass in an empty stream so we inherit the top
2787 // input reader output stream
2788 empty_stream_sp
, // Pass in an empty stream so we inherit the top
2789 // input reader error stream
2791 nullptr, // Pass in NULL for "editline_name" so no history is saved,
2793 debugger
.GetPrompt(), llvm::StringRef(),
2794 false, // Not multi-line
2795 debugger
.GetUseColor(), 0, *this));
2796 const bool old_async_execution
= debugger
.GetAsyncExecution();
2798 // Set synchronous execution if we are not stopping on continue
2799 if ((flags
& eHandleCommandFlagStopOnContinue
) == 0)
2800 debugger
.SetAsyncExecution(false);
2802 m_command_source_depth
++;
2803 m_command_source_dirs
.push_back(cmd_file
.CopyByRemovingLastPathComponent());
2805 debugger
.RunIOHandlerSync(io_handler_sp
);
2806 if (!m_command_source_flags
.empty())
2807 m_command_source_flags
.pop_back();
2809 m_command_source_dirs
.pop_back();
2810 m_command_source_depth
--;
2812 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
2813 debugger
.SetAsyncExecution(old_async_execution
);
2816 bool CommandInterpreter::GetSynchronous() { return m_synchronous_execution
; }
2818 void CommandInterpreter::SetSynchronous(bool value
) {
2819 m_synchronous_execution
= value
;
2822 void CommandInterpreter::OutputFormattedHelpText(Stream
&strm
,
2823 llvm::StringRef prefix
,
2824 llvm::StringRef help_text
) {
2825 const uint32_t max_columns
= m_debugger
.GetTerminalWidth();
2827 size_t line_width_max
= max_columns
- prefix
.size();
2828 if (line_width_max
< 16)
2829 line_width_max
= help_text
.size() + prefix
.size();
2831 strm
.IndentMore(prefix
.size());
2832 bool prefixed_yet
= false;
2833 // Even if we have no help text we still want to emit the command name.
2834 if (help_text
.empty())
2835 help_text
= "No help text";
2836 while (!help_text
.empty()) {
2837 // Prefix the first line, indent subsequent lines to line up
2838 if (!prefixed_yet
) {
2840 prefixed_yet
= true;
2844 // Never print more than the maximum on one line.
2845 llvm::StringRef this_line
= help_text
.substr(0, line_width_max
);
2847 // Always break on an explicit newline.
2848 std::size_t first_newline
= this_line
.find_first_of("\n");
2850 // Don't break on space/tab unless the text is too long to fit on one line.
2851 std::size_t last_space
= llvm::StringRef::npos
;
2852 if (this_line
.size() != help_text
.size())
2853 last_space
= this_line
.find_last_of(" \t");
2855 // Break at whichever condition triggered first.
2856 this_line
= this_line
.substr(0, std::min(first_newline
, last_space
));
2857 strm
.PutCString(this_line
);
2860 // Remove whitespace / newlines after breaking.
2861 help_text
= help_text
.drop_front(this_line
.size()).ltrim();
2863 strm
.IndentLess(prefix
.size());
2866 void CommandInterpreter::OutputFormattedHelpText(Stream
&strm
,
2867 llvm::StringRef word_text
,
2868 llvm::StringRef separator
,
2869 llvm::StringRef help_text
,
2870 size_t max_word_len
) {
2871 StreamString prefix_stream
;
2872 prefix_stream
.Printf(" %-*s %*s ", (int)max_word_len
, word_text
.data(),
2873 (int)separator
.size(), separator
.data());
2874 OutputFormattedHelpText(strm
, prefix_stream
.GetString(), help_text
);
2877 void CommandInterpreter::OutputHelpText(Stream
&strm
, llvm::StringRef word_text
,
2878 llvm::StringRef separator
,
2879 llvm::StringRef help_text
,
2880 uint32_t max_word_len
) {
2881 int indent_size
= max_word_len
+ separator
.size() + 2;
2883 strm
.IndentMore(indent_size
);
2885 StreamString text_strm
;
2886 text_strm
.Printf("%-*s ", (int)max_word_len
, word_text
.data());
2887 text_strm
<< separator
<< " " << help_text
;
2889 const uint32_t max_columns
= m_debugger
.GetTerminalWidth();
2891 llvm::StringRef text
= text_strm
.GetString();
2893 uint32_t chars_left
= max_columns
;
2895 auto nextWordLength
= [](llvm::StringRef S
) {
2896 size_t pos
= S
.find(' ');
2897 return pos
== llvm::StringRef::npos
? S
.size() : pos
;
2900 while (!text
.empty()) {
2901 if (text
.front() == '\n' ||
2902 (text
.front() == ' ' && nextWordLength(text
.ltrim(' ')) > chars_left
)) {
2905 chars_left
= max_columns
- indent_size
;
2906 if (text
.front() == '\n')
2907 text
= text
.drop_front();
2909 text
= text
.ltrim(' ');
2911 strm
.PutChar(text
.front());
2913 text
= text
.drop_front();
2918 strm
.IndentLess(indent_size
);
2921 void CommandInterpreter::FindCommandsForApropos(
2922 llvm::StringRef search_word
, StringList
&commands_found
,
2923 StringList
&commands_help
, const CommandObject::CommandMap
&command_map
) {
2924 for (const auto &pair
: command_map
) {
2925 llvm::StringRef command_name
= pair
.first
;
2926 CommandObject
*cmd_obj
= pair
.second
.get();
2928 const bool search_short_help
= true;
2929 const bool search_long_help
= false;
2930 const bool search_syntax
= false;
2931 const bool search_options
= false;
2932 if (command_name
.contains_insensitive(search_word
) ||
2933 cmd_obj
->HelpTextContainsWord(search_word
, search_short_help
,
2934 search_long_help
, search_syntax
,
2936 commands_found
.AppendString(command_name
);
2937 commands_help
.AppendString(cmd_obj
->GetHelp());
2940 if (auto *multiword_cmd
= cmd_obj
->GetAsMultiwordCommand()) {
2941 StringList subcommands_found
;
2942 FindCommandsForApropos(search_word
, subcommands_found
, commands_help
,
2943 multiword_cmd
->GetSubcommandDictionary());
2944 for (const auto &subcommand_name
: subcommands_found
) {
2945 std::string qualified_name
=
2946 (command_name
+ " " + subcommand_name
).str();
2947 commands_found
.AppendString(qualified_name
);
2953 void CommandInterpreter::FindCommandsForApropos(llvm::StringRef search_word
,
2954 StringList
&commands_found
,
2955 StringList
&commands_help
,
2956 bool search_builtin_commands
,
2957 bool search_user_commands
,
2958 bool search_alias_commands
,
2959 bool search_user_mw_commands
) {
2960 CommandObject::CommandMap::const_iterator pos
;
2962 if (search_builtin_commands
)
2963 FindCommandsForApropos(search_word
, commands_found
, commands_help
,
2966 if (search_user_commands
)
2967 FindCommandsForApropos(search_word
, commands_found
, commands_help
,
2970 if (search_user_mw_commands
)
2971 FindCommandsForApropos(search_word
, commands_found
, commands_help
,
2974 if (search_alias_commands
)
2975 FindCommandsForApropos(search_word
, commands_found
, commands_help
,
2979 ExecutionContext
CommandInterpreter::GetExecutionContext() const {
2980 return !m_overriden_exe_contexts
.empty()
2981 ? m_overriden_exe_contexts
.top()
2982 : m_debugger
.GetSelectedExecutionContext();
2985 void CommandInterpreter::OverrideExecutionContext(
2986 const ExecutionContext
&override_context
) {
2987 m_overriden_exe_contexts
.push(override_context
);
2990 void CommandInterpreter::RestoreExecutionContext() {
2991 if (!m_overriden_exe_contexts
.empty())
2992 m_overriden_exe_contexts
.pop();
2995 void CommandInterpreter::GetProcessOutput() {
2996 if (ProcessSP process_sp
= GetExecutionContext().GetProcessSP())
2997 m_debugger
.FlushProcessOutput(*process_sp
, /*flush_stdout*/ true,
2998 /*flush_stderr*/ true);
3001 void CommandInterpreter::StartHandlingCommand() {
3002 auto idle_state
= CommandHandlingState::eIdle
;
3003 if (m_command_state
.compare_exchange_strong(
3004 idle_state
, CommandHandlingState::eInProgress
))
3005 lldbassert(m_iohandler_nesting_level
== 0);
3007 lldbassert(m_iohandler_nesting_level
> 0);
3008 ++m_iohandler_nesting_level
;
3011 void CommandInterpreter::FinishHandlingCommand() {
3012 lldbassert(m_iohandler_nesting_level
> 0);
3013 if (--m_iohandler_nesting_level
== 0) {
3014 auto prev_state
= m_command_state
.exchange(CommandHandlingState::eIdle
);
3015 lldbassert(prev_state
!= CommandHandlingState::eIdle
);
3019 bool CommandInterpreter::InterruptCommand() {
3020 auto in_progress
= CommandHandlingState::eInProgress
;
3021 return m_command_state
.compare_exchange_strong(
3022 in_progress
, CommandHandlingState::eInterrupted
);
3025 bool CommandInterpreter::WasInterrupted() const {
3026 if (!m_debugger
.IsIOHandlerThreadCurrentThread())
3029 bool was_interrupted
=
3030 (m_command_state
== CommandHandlingState::eInterrupted
);
3031 lldbassert(!was_interrupted
|| m_iohandler_nesting_level
> 0);
3032 return was_interrupted
;
3035 void CommandInterpreter::PrintCommandOutput(IOHandler
&io_handler
,
3036 llvm::StringRef str
,
3039 lldb::StreamFileSP stream
= is_stdout
? io_handler
.GetOutputStreamFileSP()
3040 : io_handler
.GetErrorStreamFileSP();
3041 // Split the output into lines and poll for interrupt requests
3042 bool had_output
= !str
.empty();
3043 while (!str
.empty()) {
3044 llvm::StringRef line
;
3045 std::tie(line
, str
) = str
.split('\n');
3047 std::lock_guard
<std::recursive_mutex
> guard(io_handler
.GetOutputMutex());
3048 stream
->Write(line
.data(), line
.size());
3049 stream
->Write("\n", 1);
3053 std::lock_guard
<std::recursive_mutex
> guard(io_handler
.GetOutputMutex());
3054 if (had_output
&& INTERRUPT_REQUESTED(GetDebugger(),
3055 "Interrupted dumping command output"))
3056 stream
->Printf("\n... Interrupted.\n");
3060 bool CommandInterpreter::EchoCommandNonInteractive(
3061 llvm::StringRef line
, const Flags
&io_handler_flags
) const {
3062 if (!io_handler_flags
.Test(eHandleCommandFlagEchoCommand
))
3065 llvm::StringRef command
= line
.trim();
3066 if (command
.empty())
3069 if (command
.front() == m_comment_char
)
3070 return io_handler_flags
.Test(eHandleCommandFlagEchoCommentCommand
);
3075 void CommandInterpreter::IOHandlerInputComplete(IOHandler
&io_handler
,
3076 std::string
&line
) {
3077 // If we were interrupted, bail out...
3078 if (WasInterrupted())
3081 const bool is_interactive
= io_handler
.GetIsInteractive();
3082 if (!is_interactive
) {
3083 // When we are not interactive, don't execute blank lines. This will happen
3084 // sourcing a commands file. We don't want blank lines to repeat the
3085 // previous command and cause any errors to occur (like redefining an
3086 // alias, get an error and stop parsing the commands file).
3090 // When using a non-interactive file handle (like when sourcing commands
3091 // from a file) we need to echo the command out so we don't just see the
3092 // command output and no command...
3093 if (EchoCommandNonInteractive(line
, io_handler
.GetFlags())) {
3094 std::lock_guard
<std::recursive_mutex
> guard(io_handler
.GetOutputMutex());
3095 io_handler
.GetOutputStreamFileSP()->Printf(
3096 "%s%s\n", io_handler
.GetPrompt(), line
.c_str());
3100 StartHandlingCommand();
3102 ExecutionContext exe_ctx
= m_debugger
.GetSelectedExecutionContext();
3103 bool pushed_exe_ctx
= false;
3104 if (exe_ctx
.HasTargetScope()) {
3105 OverrideExecutionContext(exe_ctx
);
3106 pushed_exe_ctx
= true;
3108 auto finalize
= llvm::make_scope_exit([this, pushed_exe_ctx
]() {
3110 RestoreExecutionContext();
3113 lldb_private::CommandReturnObject
result(m_debugger
.GetUseColor());
3114 HandleCommand(line
.c_str(), eLazyBoolCalculate
, result
);
3116 // Now emit the command output text from the command we just executed
3117 if ((result
.Succeeded() &&
3118 io_handler
.GetFlags().Test(eHandleCommandFlagPrintResult
)) ||
3119 io_handler
.GetFlags().Test(eHandleCommandFlagPrintErrors
)) {
3120 // Display any STDOUT/STDERR _prior_ to emitting the command result text
3123 if (!result
.GetImmediateOutputStream()) {
3124 llvm::StringRef output
= result
.GetOutputData();
3125 PrintCommandOutput(io_handler
, output
, true);
3128 // Now emit the command error text from the command we just executed
3129 if (!result
.GetImmediateErrorStream()) {
3130 llvm::StringRef error
= result
.GetErrorData();
3131 PrintCommandOutput(io_handler
, error
, false);
3135 FinishHandlingCommand();
3137 switch (result
.GetStatus()) {
3138 case eReturnStatusInvalid
:
3139 case eReturnStatusSuccessFinishNoResult
:
3140 case eReturnStatusSuccessFinishResult
:
3141 case eReturnStatusStarted
:
3144 case eReturnStatusSuccessContinuingNoResult
:
3145 case eReturnStatusSuccessContinuingResult
:
3146 if (io_handler
.GetFlags().Test(eHandleCommandFlagStopOnContinue
))
3147 io_handler
.SetIsDone(true);
3150 case eReturnStatusFailed
:
3151 m_result
.IncrementNumberOfErrors();
3152 if (io_handler
.GetFlags().Test(eHandleCommandFlagStopOnError
)) {
3153 m_result
.SetResult(lldb::eCommandInterpreterResultCommandError
);
3154 io_handler
.SetIsDone(true);
3158 case eReturnStatusQuit
:
3159 m_result
.SetResult(lldb::eCommandInterpreterResultQuitRequested
);
3160 io_handler
.SetIsDone(true);
3164 // Finally, if we're going to stop on crash, check that here:
3165 if (m_result
.IsResult(lldb::eCommandInterpreterResultSuccess
) &&
3166 result
.GetDidChangeProcessState() &&
3167 io_handler
.GetFlags().Test(eHandleCommandFlagStopOnCrash
) &&
3168 DidProcessStopAbnormally()) {
3169 io_handler
.SetIsDone(true);
3170 m_result
.SetResult(lldb::eCommandInterpreterResultInferiorCrash
);
3174 bool CommandInterpreter::IOHandlerInterrupt(IOHandler
&io_handler
) {
3175 ExecutionContext
exe_ctx(GetExecutionContext());
3176 Process
*process
= exe_ctx
.GetProcessPtr();
3178 if (InterruptCommand())
3182 StateType state
= process
->GetState();
3183 if (StateIsRunningState(state
)) {
3185 return true; // Don't do any updating when we are running
3189 ScriptInterpreter
*script_interpreter
=
3190 m_debugger
.GetScriptInterpreter(false);
3191 if (script_interpreter
) {
3192 if (script_interpreter
->Interrupt())
3198 bool CommandInterpreter::SaveTranscript(
3199 CommandReturnObject
&result
, std::optional
<std::string
> output_file
) {
3200 if (output_file
== std::nullopt
|| output_file
->empty()) {
3201 std::string now
= llvm::to_string(std::chrono::system_clock::now());
3202 std::replace(now
.begin(), now
.end(), ' ', '_');
3203 const std::string file_name
= "lldb_session_" + now
+ ".log";
3205 FileSpec save_location
= GetSaveSessionDirectory();
3208 save_location
= HostInfo::GetGlobalTempDir();
3210 FileSystem::Instance().Resolve(save_location
);
3211 save_location
.AppendPathComponent(file_name
);
3212 output_file
= save_location
.GetPath();
3215 auto error_out
= [&](llvm::StringRef error_message
, std::string description
) {
3216 LLDB_LOG(GetLog(LLDBLog::Commands
), "{0} ({1}:{2})", error_message
,
3217 output_file
, description
);
3218 result
.AppendErrorWithFormatv(
3219 "Failed to save session's transcripts to {0}!", *output_file
);
3223 File::OpenOptions flags
= File::eOpenOptionWriteOnly
|
3224 File::eOpenOptionCanCreate
|
3225 File::eOpenOptionTruncate
;
3227 auto opened_file
= FileSystem::Instance().Open(FileSpec(*output_file
), flags
);
3230 return error_out("Unable to create file",
3231 llvm::toString(opened_file
.takeError()));
3233 FileUP file
= std::move(opened_file
.get());
3235 size_t byte_size
= m_transcript_stream
.GetSize();
3237 Status error
= file
->Write(m_transcript_stream
.GetData(), byte_size
);
3239 if (error
.Fail() || byte_size
!= m_transcript_stream
.GetSize())
3240 return error_out("Unable to write to destination file",
3241 "Bytes written do not match transcript size.");
3243 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
3244 result
.AppendMessageWithFormat("Session's transcripts saved to %s\n",
3245 output_file
->c_str());
3247 if (GetOpenTranscriptInEditor() && Host::IsInteractiveGraphicSession()) {
3248 const FileSpec file_spec
;
3249 error
= file
->GetFileSpec(const_cast<FileSpec
&>(file_spec
));
3250 if (error
.Success()) {
3251 if (llvm::Error e
= Host::OpenFileInExternalEditor(
3252 m_debugger
.GetExternalEditor(), file_spec
, 1))
3253 result
.AppendError(llvm::toString(std::move(e
)));
3260 bool CommandInterpreter::IsInteractive() {
3261 return (GetIOHandler() ? GetIOHandler()->GetIsInteractive() : false);
3264 FileSpec
CommandInterpreter::GetCurrentSourceDir() {
3265 if (m_command_source_dirs
.empty())
3267 return m_command_source_dirs
.back();
3270 void CommandInterpreter::GetLLDBCommandsFromIOHandler(
3271 const char *prompt
, IOHandlerDelegate
&delegate
, void *baton
) {
3272 Debugger
&debugger
= GetDebugger();
3273 IOHandlerSP
io_handler_sp(
3274 new IOHandlerEditline(debugger
, IOHandler::Type::CommandList
,
3275 "lldb", // Name of input reader for history
3276 llvm::StringRef(prompt
), // Prompt
3277 llvm::StringRef(), // Continuation prompt
3278 true, // Get multiple lines
3279 debugger
.GetUseColor(),
3280 0, // Don't show line numbers
3281 delegate
)); // IOHandlerDelegate
3283 if (io_handler_sp
) {
3284 io_handler_sp
->SetUserData(baton
);
3285 debugger
.RunIOHandlerAsync(io_handler_sp
);
3289 void CommandInterpreter::GetPythonCommandsFromIOHandler(
3290 const char *prompt
, IOHandlerDelegate
&delegate
, void *baton
) {
3291 Debugger
&debugger
= GetDebugger();
3292 IOHandlerSP
io_handler_sp(
3293 new IOHandlerEditline(debugger
, IOHandler::Type::PythonCode
,
3294 "lldb-python", // Name of input reader for history
3295 llvm::StringRef(prompt
), // Prompt
3296 llvm::StringRef(), // Continuation prompt
3297 true, // Get multiple lines
3298 debugger
.GetUseColor(),
3299 0, // Don't show line numbers
3300 delegate
)); // IOHandlerDelegate
3302 if (io_handler_sp
) {
3303 io_handler_sp
->SetUserData(baton
);
3304 debugger
.RunIOHandlerAsync(io_handler_sp
);
3308 bool CommandInterpreter::IsActive() {
3309 return m_debugger
.IsTopIOHandler(m_command_io_handler_sp
);
3313 CommandInterpreter::GetIOHandler(bool force_create
,
3314 CommandInterpreterRunOptions
*options
) {
3315 // Always re-create the IOHandlerEditline in case the input changed. The old
3316 // instance might have had a non-interactive input and now it does or vice
3318 if (force_create
|| !m_command_io_handler_sp
) {
3319 // Always re-create the IOHandlerEditline in case the input changed. The
3320 // old instance might have had a non-interactive input and now it does or
3325 if (options
->m_stop_on_continue
== eLazyBoolYes
)
3326 flags
|= eHandleCommandFlagStopOnContinue
;
3327 if (options
->m_stop_on_error
== eLazyBoolYes
)
3328 flags
|= eHandleCommandFlagStopOnError
;
3329 if (options
->m_stop_on_crash
== eLazyBoolYes
)
3330 flags
|= eHandleCommandFlagStopOnCrash
;
3331 if (options
->m_echo_commands
!= eLazyBoolNo
)
3332 flags
|= eHandleCommandFlagEchoCommand
;
3333 if (options
->m_echo_comment_commands
!= eLazyBoolNo
)
3334 flags
|= eHandleCommandFlagEchoCommentCommand
;
3335 if (options
->m_print_results
!= eLazyBoolNo
)
3336 flags
|= eHandleCommandFlagPrintResult
;
3337 if (options
->m_print_errors
!= eLazyBoolNo
)
3338 flags
|= eHandleCommandFlagPrintErrors
;
3340 flags
= eHandleCommandFlagEchoCommand
| eHandleCommandFlagPrintResult
|
3341 eHandleCommandFlagPrintErrors
;
3344 m_command_io_handler_sp
= std::make_shared
<IOHandlerEditline
>(
3345 m_debugger
, IOHandler::Type::CommandInterpreter
,
3346 m_debugger
.GetInputFileSP(), m_debugger
.GetOutputStreamSP(),
3347 m_debugger
.GetErrorStreamSP(), flags
, "lldb", m_debugger
.GetPrompt(),
3348 llvm::StringRef(), // Continuation prompt
3349 false, // Don't enable multiple line input, just single line commands
3350 m_debugger
.GetUseColor(),
3351 0, // Don't show line numbers
3352 *this); // IOHandlerDelegate
3354 return m_command_io_handler_sp
;
3357 CommandInterpreterRunResult
CommandInterpreter::RunCommandInterpreter(
3358 CommandInterpreterRunOptions
&options
) {
3359 // Always re-create the command interpreter when we run it in case any file
3360 // handles have changed.
3361 bool force_create
= true;
3362 m_debugger
.RunIOHandlerAsync(GetIOHandler(force_create
, &options
));
3363 m_result
= CommandInterpreterRunResult();
3365 if (options
.GetAutoHandleEvents())
3366 m_debugger
.StartEventHandlerThread();
3368 if (options
.GetSpawnThread()) {
3369 m_debugger
.StartIOHandlerThread();
3371 // If the current thread is not managed by a host thread, we won't detect
3372 // that this IS the CommandInterpreter IOHandler thread, so make it so:
3373 HostThread
new_io_handler_thread(Host::GetCurrentThread());
3374 HostThread old_io_handler_thread
=
3375 m_debugger
.SetIOHandlerThread(new_io_handler_thread
);
3376 m_debugger
.RunIOHandlers();
3377 m_debugger
.SetIOHandlerThread(old_io_handler_thread
);
3379 if (options
.GetAutoHandleEvents())
3380 m_debugger
.StopEventHandlerThread();
3387 CommandInterpreter::ResolveCommandImpl(std::string
&command_line
,
3388 CommandReturnObject
&result
) {
3389 std::string
scratch_command(command_line
); // working copy so we don't modify
3390 // command_line unless we succeed
3391 CommandObject
*cmd_obj
= nullptr;
3392 StreamString revised_command_line
;
3393 bool wants_raw_input
= false;
3394 std::string next_word
;
3398 char quote_char
= '\0';
3400 ExtractCommand(scratch_command
, next_word
, suffix
, quote_char
);
3401 if (cmd_obj
== nullptr) {
3402 std::string full_name
;
3403 bool is_alias
= GetAliasFullName(next_word
, full_name
);
3404 cmd_obj
= GetCommandObject(next_word
, &matches
);
3405 bool is_real_command
=
3406 (!is_alias
) || (cmd_obj
!= nullptr && !cmd_obj
->IsAlias());
3407 if (!is_real_command
) {
3409 std::string alias_result
;
3411 BuildAliasResult(full_name
, scratch_command
, alias_result
, result
);
3412 revised_command_line
.Printf("%s", alias_result
.c_str());
3414 wants_raw_input
= cmd_obj
->WantsRawCommandString();
3418 llvm::StringRef cmd_name
= cmd_obj
->GetCommandName();
3419 revised_command_line
.Printf("%s", cmd_name
.str().c_str());
3420 wants_raw_input
= cmd_obj
->WantsRawCommandString();
3422 revised_command_line
.Printf("%s", next_word
.c_str());
3426 if (cmd_obj
->IsMultiwordObject()) {
3427 CommandObject
*sub_cmd_obj
=
3428 cmd_obj
->GetSubcommandObject(next_word
.c_str());
3430 // The subcommand's name includes the parent command's name, so
3431 // restart rather than append to the revised_command_line.
3432 llvm::StringRef sub_cmd_name
= sub_cmd_obj
->GetCommandName();
3433 revised_command_line
.Clear();
3434 revised_command_line
.Printf("%s", sub_cmd_name
.str().c_str());
3435 cmd_obj
= sub_cmd_obj
;
3436 wants_raw_input
= cmd_obj
->WantsRawCommandString();
3439 revised_command_line
.Printf(" %c%s%s%c", quote_char
,
3440 next_word
.c_str(), suffix
.c_str(),
3443 revised_command_line
.Printf(" %s%s", next_word
.c_str(),
3449 revised_command_line
.Printf(" %c%s%s%c", quote_char
,
3450 next_word
.c_str(), suffix
.c_str(),
3453 revised_command_line
.Printf(" %s%s", next_word
.c_str(),
3459 if (cmd_obj
== nullptr) {
3460 const size_t num_matches
= matches
.GetSize();
3461 if (matches
.GetSize() > 1) {
3462 StreamString error_msg
;
3463 error_msg
.Printf("Ambiguous command '%s'. Possible matches:\n",
3466 for (uint32_t i
= 0; i
< num_matches
; ++i
) {
3467 error_msg
.Printf("\t%s\n", matches
.GetStringAtIndex(i
));
3469 result
.AppendRawError(error_msg
.GetString());
3471 // We didn't have only one match, otherwise we wouldn't get here.
3472 lldbassert(num_matches
== 0);
3473 result
.AppendErrorWithFormat("'%s' is not a valid command.\n",
3479 if (cmd_obj
->IsMultiwordObject()) {
3480 if (!suffix
.empty()) {
3481 result
.AppendErrorWithFormat(
3482 "command '%s' did not recognize '%s%s%s' as valid (subcommand "
3483 "might be invalid).\n",
3484 cmd_obj
->GetCommandName().str().c_str(),
3485 next_word
.empty() ? "" : next_word
.c_str(),
3486 next_word
.empty() ? " -- " : " ", suffix
.c_str());
3490 // If we found a normal command, we are done
3492 if (!suffix
.empty()) {
3493 switch (suffix
[0]) {
3495 // GDB format suffixes
3497 Options
*command_options
= cmd_obj
->GetOptions();
3498 if (command_options
&&
3499 command_options
->SupportsLongOption("gdb-format")) {
3500 std::string
gdb_format_option("--gdb-format=");
3501 gdb_format_option
+= (suffix
.c_str() + 1);
3503 std::string cmd
= std::string(revised_command_line
.GetString());
3504 size_t arg_terminator_idx
= FindArgumentTerminator(cmd
);
3505 if (arg_terminator_idx
!= std::string::npos
) {
3506 // Insert the gdb format option before the "--" that terminates
3508 gdb_format_option
.append(1, ' ');
3509 cmd
.insert(arg_terminator_idx
, gdb_format_option
);
3510 revised_command_line
.Clear();
3511 revised_command_line
.PutCString(cmd
);
3513 revised_command_line
.Printf(" %s", gdb_format_option
.c_str());
3515 if (wants_raw_input
&&
3516 FindArgumentTerminator(cmd
) == std::string::npos
)
3517 revised_command_line
.PutCString(" --");
3519 result
.AppendErrorWithFormat(
3520 "the '%s' command doesn't support the --gdb-format option\n",
3521 cmd_obj
->GetCommandName().str().c_str());
3528 result
.AppendErrorWithFormat(
3529 "unknown command shorthand suffix: '%s'\n", suffix
.c_str());
3534 if (scratch_command
.empty())
3538 if (!scratch_command
.empty())
3539 revised_command_line
.Printf(" %s", scratch_command
.c_str());
3541 if (cmd_obj
!= nullptr)
3542 command_line
= std::string(revised_command_line
.GetString());