LLDB mainline
CommandInterpreter.cpp
Go to the documentation of this file.
1//===-- CommandInterpreter.cpp --------------------------------------------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8
9#include <chrono>
10#include <cstdlib>
11#include <limits>
12#include <memory>
13#include <optional>
14#include <string>
15#include <vector>
16
47
48#include "lldb/Core/Debugger.h"
53#include "lldb/Utility/Log.h"
54#include "lldb/Utility/State.h"
55#include "lldb/Utility/Stream.h"
57#include "lldb/Utility/Timer.h"
58
59#include "lldb/Host/Config.h"
60#if LLDB_ENABLE_LIBEDIT
61#include "lldb/Host/Editline.h"
62#endif
63#include "lldb/Host/File.h"
64#include "lldb/Host/FileCache.h"
65#include "lldb/Host/Host.h"
66#include "lldb/Host/HostInfo.h"
67
74#include "lldb/Utility/Args.h"
75
77#include "lldb/Target/Process.h"
80#include "lldb/Target/Thread.h"
82
83#include "llvm/ADT/STLExtras.h"
84#include "llvm/ADT/ScopeExit.h"
85#include "llvm/ADT/SmallString.h"
86#include "llvm/Support/FormatAdapters.h"
87#include "llvm/Support/Path.h"
88#include "llvm/Support/PrettyStackTrace.h"
89#include "llvm/Support/ScopedPrinter.h"
90
91#if defined(__APPLE__)
92#include <TargetConditionals.h>
93#endif
94
95using namespace lldb;
96using namespace lldb_private;
97
98static const char *k_white_space = " \t\v";
99
100static constexpr const char *InitFileWarning =
101 "There is a .lldbinit file in the current directory which is not being "
102 "read.\n"
103 "To silence this warning without sourcing in the local .lldbinit,\n"
104 "add the following to the lldbinit file in your home directory:\n"
105 " settings set target.load-cwd-lldbinit false\n"
106 "To allow lldb to source .lldbinit files in the current working "
107 "directory,\n"
108 "set the value of this variable to true. Only do so if you understand "
109 "and\n"
110 "accept the security risk.";
111
112const char *CommandInterpreter::g_no_argument = "<no-argument>";
113const char *CommandInterpreter::g_need_argument = "<need-argument>";
114const char *CommandInterpreter::g_argument = "<argument>";
115
116
117#define LLDB_PROPERTIES_interpreter
118#include "InterpreterProperties.inc"
119
120enum {
121#define LLDB_PROPERTIES_interpreter
122#include "InterpreterPropertiesEnum.inc"
123};
124
126 static constexpr llvm::StringLiteral class_name("lldb.commandInterpreter");
127 return class_name;
128}
129
131 bool synchronous_execution)
132 : Broadcaster(debugger.GetBroadcasterManager(),
133 CommandInterpreter::GetStaticBroadcasterClass().str()),
137 m_debugger(debugger), m_synchronous_execution(true),
138 m_skip_lldbinit_files(false), m_skip_app_init_files(false),
139 m_comment_char('#'), m_batch_command_mode(false),
140 m_truncation_warning(eNoOmission), m_max_depth_warning(eNoOmission),
141 m_command_source_depth(0) {
142 SetEventName(eBroadcastBitThreadShouldExit, "thread-should-exit");
143 SetEventName(eBroadcastBitResetPrompt, "reset-prompt");
145 SetSynchronous(synchronous_execution);
147 m_collection_sp->Initialize(g_interpreter_properties);
148}
149
151 const uint32_t idx = ePropertyExpandRegexAliases;
152 return GetPropertyAtIndexAs<bool>(
153 idx, g_interpreter_properties[idx].default_uint_value != 0);
154}
155
157 const uint32_t idx = ePropertyPromptOnQuit;
158 return GetPropertyAtIndexAs<bool>(
159 idx, g_interpreter_properties[idx].default_uint_value != 0);
160}
161
163 const uint32_t idx = ePropertyPromptOnQuit;
164 SetPropertyAtIndex(idx, enable);
165}
166
168 const uint32_t idx = ePropertySaveTranscript;
169 return GetPropertyAtIndexAs<bool>(
170 idx, g_interpreter_properties[idx].default_uint_value != 0);
171}
172
174 const uint32_t idx = ePropertySaveTranscript;
175 SetPropertyAtIndex(idx, enable);
176}
177
179 const uint32_t idx = ePropertySaveSessionOnQuit;
180 return GetPropertyAtIndexAs<bool>(
181 idx, g_interpreter_properties[idx].default_uint_value != 0);
182}
183
185 const uint32_t idx = ePropertySaveSessionOnQuit;
186 SetPropertyAtIndex(idx, enable);
187}
188
190 const uint32_t idx = ePropertyOpenTranscriptInEditor;
191 return GetPropertyAtIndexAs<bool>(
192 idx, g_interpreter_properties[idx].default_uint_value != 0);
193}
194
196 const uint32_t idx = ePropertyOpenTranscriptInEditor;
197 SetPropertyAtIndex(idx, enable);
198}
199
201 const uint32_t idx = ePropertySaveSessionDirectory;
202 return GetPropertyAtIndexAs<FileSpec>(idx, {});
203}
204
206 const uint32_t idx = ePropertySaveSessionDirectory;
207 SetPropertyAtIndex(idx, path);
208}
209
211 const uint32_t idx = ePropertyEchoCommands;
212 return GetPropertyAtIndexAs<bool>(
213 idx, g_interpreter_properties[idx].default_uint_value != 0);
214}
215
217 const uint32_t idx = ePropertyEchoCommands;
218 SetPropertyAtIndex(idx, enable);
219}
220
222 const uint32_t idx = ePropertyEchoCommentCommands;
223 return GetPropertyAtIndexAs<bool>(
224 idx, g_interpreter_properties[idx].default_uint_value != 0);
225}
226
228 const uint32_t idx = ePropertyEchoCommentCommands;
229 SetPropertyAtIndex(idx, enable);
230}
231
233 m_allow_exit_code = allow;
234 if (!allow)
235 m_quit_exit_code.reset();
236}
237
240 return false;
241 m_quit_exit_code = exit_code;
242 return true;
243}
244
245int CommandInterpreter::GetQuitExitCode(bool &exited) const {
246 exited = m_quit_exit_code.has_value();
247 if (exited)
248 return *m_quit_exit_code;
249 return 0;
250}
251
252void CommandInterpreter::ResolveCommand(const char *command_line,
253 CommandReturnObject &result) {
254 std::string command = command_line;
255 if (ResolveCommandImpl(command, result) != nullptr) {
256 result.AppendMessageWithFormat("%s", command.c_str());
258 }
259}
260
262 const uint32_t idx = ePropertyStopCmdSourceOnError;
263 return GetPropertyAtIndexAs<bool>(
264 idx, g_interpreter_properties[idx].default_uint_value != 0);
265}
266
268 const uint32_t idx = ePropertySpaceReplPrompts;
269 return GetPropertyAtIndexAs<bool>(
270 idx, g_interpreter_properties[idx].default_uint_value != 0);
271}
272
274 const uint32_t idx = ePropertyRepeatPreviousCommand;
275 return GetPropertyAtIndexAs<bool>(
276 idx, g_interpreter_properties[idx].default_uint_value != 0);
277}
278
280 const uint32_t idx = ePropertyRequireCommandOverwrite;
281 return GetPropertyAtIndexAs<bool>(
282 idx, g_interpreter_properties[idx].default_uint_value != 0);
283}
284
287
289
291
292 // An alias arguments vector to reuse - reset it before use...
293 OptionArgVectorSP alias_arguments_vector_sp(new OptionArgVector);
294
295 // Set up some initial aliases.
296 CommandObjectSP cmd_obj_sp = GetCommandSPExact("quit");
297 if (cmd_obj_sp) {
298 AddAlias("q", cmd_obj_sp);
299 AddAlias("exit", cmd_obj_sp);
300 }
301
302 cmd_obj_sp = GetCommandSPExact("_regexp-attach");
303 if (cmd_obj_sp)
304 AddAlias("attach", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
305
306 cmd_obj_sp = GetCommandSPExact("process detach");
307 if (cmd_obj_sp) {
308 AddAlias("detach", cmd_obj_sp);
309 }
310
311 cmd_obj_sp = GetCommandSPExact("process continue");
312 if (cmd_obj_sp) {
313 AddAlias("c", cmd_obj_sp);
314 AddAlias("continue", cmd_obj_sp);
315 }
316
317 cmd_obj_sp = GetCommandSPExact("_regexp-break");
318 if (cmd_obj_sp)
319 AddAlias("b", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
320
321 cmd_obj_sp = GetCommandSPExact("_regexp-tbreak");
322 if (cmd_obj_sp)
323 AddAlias("tbreak", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
324
325 cmd_obj_sp = GetCommandSPExact("thread step-inst");
326 if (cmd_obj_sp) {
327 AddAlias("stepi", cmd_obj_sp);
328 AddAlias("si", cmd_obj_sp);
329 }
330
331 cmd_obj_sp = GetCommandSPExact("thread step-inst-over");
332 if (cmd_obj_sp) {
333 AddAlias("nexti", cmd_obj_sp);
334 AddAlias("ni", cmd_obj_sp);
335 }
336
337 cmd_obj_sp = GetCommandSPExact("thread step-in");
338 if (cmd_obj_sp) {
339 AddAlias("s", cmd_obj_sp);
340 AddAlias("step", cmd_obj_sp);
341 CommandAlias *sif_alias = AddAlias(
342 "sif", cmd_obj_sp, "--end-linenumber block --step-in-target %1");
343 if (sif_alias) {
344 sif_alias->SetHelp("Step through the current block, stopping if you step "
345 "directly into a function whose name matches the "
346 "TargetFunctionName.");
347 sif_alias->SetSyntax("sif <TargetFunctionName>");
348 }
349 }
350
351 cmd_obj_sp = GetCommandSPExact("thread step-over");
352 if (cmd_obj_sp) {
353 AddAlias("n", cmd_obj_sp);
354 AddAlias("next", cmd_obj_sp);
355 }
356
357 cmd_obj_sp = GetCommandSPExact("thread step-out");
358 if (cmd_obj_sp) {
359 AddAlias("finish", cmd_obj_sp);
360 }
361
362 cmd_obj_sp = GetCommandSPExact("frame select");
363 if (cmd_obj_sp) {
364 AddAlias("f", cmd_obj_sp);
365 }
366
367 cmd_obj_sp = GetCommandSPExact("thread select");
368 if (cmd_obj_sp) {
369 AddAlias("t", cmd_obj_sp);
370 }
371
372 cmd_obj_sp = GetCommandSPExact("_regexp-jump");
373 if (cmd_obj_sp) {
374 AddAlias("j", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
375 AddAlias("jump", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
376 }
377
378 cmd_obj_sp = GetCommandSPExact("_regexp-list");
379 if (cmd_obj_sp) {
380 AddAlias("l", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
381 AddAlias("list", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
382 }
383
384 cmd_obj_sp = GetCommandSPExact("_regexp-env");
385 if (cmd_obj_sp)
386 AddAlias("env", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
387
388 cmd_obj_sp = GetCommandSPExact("memory read");
389 if (cmd_obj_sp)
390 AddAlias("x", cmd_obj_sp);
391
392 cmd_obj_sp = GetCommandSPExact("_regexp-up");
393 if (cmd_obj_sp)
394 AddAlias("up", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
395
396 cmd_obj_sp = GetCommandSPExact("_regexp-down");
397 if (cmd_obj_sp)
398 AddAlias("down", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
399
400 cmd_obj_sp = GetCommandSPExact("_regexp-display");
401 if (cmd_obj_sp)
402 AddAlias("display", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
403
404 cmd_obj_sp = GetCommandSPExact("disassemble");
405 if (cmd_obj_sp)
406 AddAlias("dis", cmd_obj_sp);
407
408 cmd_obj_sp = GetCommandSPExact("disassemble");
409 if (cmd_obj_sp)
410 AddAlias("di", cmd_obj_sp);
411
412 cmd_obj_sp = GetCommandSPExact("_regexp-undisplay");
413 if (cmd_obj_sp)
414 AddAlias("undisplay", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
415
416 cmd_obj_sp = GetCommandSPExact("_regexp-bt");
417 if (cmd_obj_sp)
418 AddAlias("bt", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
419
420 cmd_obj_sp = GetCommandSPExact("target create");
421 if (cmd_obj_sp)
422 AddAlias("file", cmd_obj_sp);
423
424 cmd_obj_sp = GetCommandSPExact("target modules");
425 if (cmd_obj_sp)
426 AddAlias("image", cmd_obj_sp);
427
428 alias_arguments_vector_sp = std::make_shared<OptionArgVector>();
429
430 cmd_obj_sp = GetCommandSPExact("dwim-print");
431 if (cmd_obj_sp) {
432 AddAlias("p", cmd_obj_sp, "--")->SetHelpLong("");
433 AddAlias("print", cmd_obj_sp, "--")->SetHelpLong("");
434 if (auto *po = AddAlias("po", cmd_obj_sp, "-O --")) {
435 po->SetHelp("Evaluate an expression on the current thread. Displays any "
436 "returned value with formatting "
437 "controlled by the type's author.");
438 po->SetHelpLong("");
439 }
440 }
441
442 cmd_obj_sp = GetCommandSPExact("expression");
443 if (cmd_obj_sp) {
444 // Ensure `e` runs `expression`.
445 AddAlias("e", cmd_obj_sp);
446 AddAlias("call", cmd_obj_sp, "--")->SetHelpLong("");
447 CommandAlias *parray_alias =
448 AddAlias("parray", cmd_obj_sp, "--element-count %1 --");
449 if (parray_alias) {
450 parray_alias->SetHelp
451 ("parray <COUNT> <EXPRESSION> -- lldb will evaluate EXPRESSION "
452 "to get a typed-pointer-to-an-array in memory, and will display "
453 "COUNT elements of that type from the array.");
454 parray_alias->SetHelpLong("");
455 }
456 CommandAlias *poarray_alias = AddAlias("poarray", cmd_obj_sp,
457 "--object-description --element-count %1 --");
458 if (poarray_alias) {
459 poarray_alias->SetHelp("poarray <COUNT> <EXPRESSION> -- lldb will "
460 "evaluate EXPRESSION to get the address of an array of COUNT "
461 "objects in memory, and will call po on them.");
462 poarray_alias->SetHelpLong("");
463 }
464 }
465
466 cmd_obj_sp = GetCommandSPExact("platform shell");
467 if (cmd_obj_sp) {
468 CommandAlias *shell_alias = AddAlias("shell", cmd_obj_sp, " --host --");
469 if (shell_alias) {
470 shell_alias->SetHelp("Run a shell command on the host.");
471 shell_alias->SetHelpLong("");
472 shell_alias->SetSyntax("shell <shell-command>");
473 }
474 }
475
476 cmd_obj_sp = GetCommandSPExact("process kill");
477 if (cmd_obj_sp) {
478 AddAlias("kill", cmd_obj_sp);
479 }
480
481 cmd_obj_sp = GetCommandSPExact("process launch");
482 if (cmd_obj_sp) {
483 alias_arguments_vector_sp = std::make_shared<OptionArgVector>();
484#if defined(__APPLE__)
485#if TARGET_OS_IPHONE
486 AddAlias("r", cmd_obj_sp, "--");
487 AddAlias("run", cmd_obj_sp, "--");
488#else
489 AddAlias("r", cmd_obj_sp, "--shell-expand-args true --");
490 AddAlias("run", cmd_obj_sp, "--shell-expand-args true --");
491#endif
492#else
493 StreamString defaultshell;
494 defaultshell.Printf("--shell=%s --",
495 HostInfo::GetDefaultShell().GetPath().c_str());
496 AddAlias("r", cmd_obj_sp, defaultshell.GetString());
497 AddAlias("run", cmd_obj_sp, defaultshell.GetString());
498#endif
499 }
500
501 cmd_obj_sp = GetCommandSPExact("target symbols add");
502 if (cmd_obj_sp) {
503 AddAlias("add-dsym", cmd_obj_sp);
504 }
505
506 cmd_obj_sp = GetCommandSPExact("breakpoint set");
507 if (cmd_obj_sp) {
508 AddAlias("rbreak", cmd_obj_sp, "--func-regex %1");
509 }
510
511 cmd_obj_sp = GetCommandSPExact("frame variable");
512 if (cmd_obj_sp) {
513 AddAlias("v", cmd_obj_sp);
514 AddAlias("var", cmd_obj_sp);
515 AddAlias("vo", cmd_obj_sp, "--object-description");
516 }
517
518 cmd_obj_sp = GetCommandSPExact("register");
519 if (cmd_obj_sp) {
520 AddAlias("re", cmd_obj_sp);
521 }
522
523 cmd_obj_sp = GetCommandSPExact("scripting run");
524 if (cmd_obj_sp) {
525 AddAlias("script", cmd_obj_sp);
526 }
527
528 cmd_obj_sp = GetCommandSPExact("session history");
529 if (cmd_obj_sp) {
530 AddAlias("history", cmd_obj_sp);
531 }
532
533 cmd_obj_sp = GetCommandSPExact("help");
534 if (cmd_obj_sp) {
535 AddAlias("h", cmd_obj_sp);
536 }
537}
538
541}
542
544 // This function has not yet been implemented.
545
546 // Look for any embedded script command
547 // If found,
548 // get interpreter object from the command dictionary,
549 // call execute_one_command on it,
550 // get the results as a string,
551 // substitute that string for current stuff.
552
553 return arg;
554}
555
556#define REGISTER_COMMAND_OBJECT(NAME, CLASS) \
557 m_command_dict[NAME] = std::make_shared<CLASS>(*this);
558
561
591
592 // clang-format off
593 const char *break_regexes[][2] = {
594 {"^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$",
595 "breakpoint set --file '%1' --line %2 --column %3"},
596 {"^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$",
597 "breakpoint set --file '%1' --line %2"},
598 {"^/([^/]+)/$", "breakpoint set --source-pattern-regexp '%1'"},
599 {"^([[:digit:]]+)[[:space:]]*$", "breakpoint set --line %1"},
600 {"^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "breakpoint set --address %1"},
601 {"^[\"']?([-+]?\\[.*\\])[\"']?[[:space:]]*$",
602 "breakpoint set --name '%1'"},
603 {"^(-.*)$", "breakpoint set %1"},
604 {"^(.*[^[:space:]])`(.*[^[:space:]])[[:space:]]*$",
605 "breakpoint set --name '%2' --shlib '%1'"},
606 {"^\\&(.*[^[:space:]])[[:space:]]*$",
607 "breakpoint set --name '%1' --skip-prologue=0"},
608 {"^[\"']?(.*[^[:space:]\"'])[\"']?[[:space:]]*$",
609 "breakpoint set --name '%1'"}};
610 // clang-format on
611
612 size_t num_regexes = std::size(break_regexes);
613
614 std::unique_ptr<CommandObjectRegexCommand> break_regex_cmd_up(
616 *this, "_regexp-break",
617 "Set a breakpoint using one of several shorthand formats.",
618 "\n"
619 "_regexp-break <filename>:<linenum>:<colnum>\n"
620 " main.c:12:21 // Break at line 12 and column "
621 "21 of main.c\n\n"
622 "_regexp-break <filename>:<linenum>\n"
623 " main.c:12 // Break at line 12 of "
624 "main.c\n\n"
625 "_regexp-break <linenum>\n"
626 " 12 // Break at line 12 of current "
627 "file\n\n"
628 "_regexp-break 0x<address>\n"
629 " 0x1234000 // Break at address "
630 "0x1234000\n\n"
631 "_regexp-break <name>\n"
632 " main // Break in 'main' after the "
633 "prologue\n\n"
634 "_regexp-break &<name>\n"
635 " &main // Break at first instruction "
636 "in 'main'\n\n"
637 "_regexp-break <module>`<name>\n"
638 " libc.so`malloc // Break in 'malloc' from "
639 "'libc.so'\n\n"
640 "_regexp-break /<source-regex>/\n"
641 " /break here/ // Break on source lines in "
642 "current file\n"
643 " // containing text 'break "
644 "here'.\n",
646
647 if (break_regex_cmd_up) {
648 bool success = true;
649 for (size_t i = 0; i < num_regexes; i++) {
650 success = break_regex_cmd_up->AddRegexCommand(break_regexes[i][0],
651 break_regexes[i][1]);
652 if (!success)
653 break;
654 }
655 success =
656 break_regex_cmd_up->AddRegexCommand("^$", "breakpoint list --full");
657
658 if (success) {
659 CommandObjectSP break_regex_cmd_sp(break_regex_cmd_up.release());
660 m_command_dict[std::string(break_regex_cmd_sp->GetCommandName())] =
661 break_regex_cmd_sp;
662 }
663 }
664
665 std::unique_ptr<CommandObjectRegexCommand> tbreak_regex_cmd_up(
667 *this, "_regexp-tbreak",
668 "Set a one-shot breakpoint using one of several shorthand formats.",
669 "\n"
670 "_regexp-break <filename>:<linenum>:<colnum>\n"
671 " main.c:12:21 // Break at line 12 and column "
672 "21 of main.c\n\n"
673 "_regexp-break <filename>:<linenum>\n"
674 " main.c:12 // Break at line 12 of "
675 "main.c\n\n"
676 "_regexp-break <linenum>\n"
677 " 12 // Break at line 12 of current "
678 "file\n\n"
679 "_regexp-break 0x<address>\n"
680 " 0x1234000 // Break at address "
681 "0x1234000\n\n"
682 "_regexp-break <name>\n"
683 " main // Break in 'main' after the "
684 "prologue\n\n"
685 "_regexp-break &<name>\n"
686 " &main // Break at first instruction "
687 "in 'main'\n\n"
688 "_regexp-break <module>`<name>\n"
689 " libc.so`malloc // Break in 'malloc' from "
690 "'libc.so'\n\n"
691 "_regexp-break /<source-regex>/\n"
692 " /break here/ // Break on source lines in "
693 "current file\n"
694 " // containing text 'break "
695 "here'.\n",
697
698 if (tbreak_regex_cmd_up) {
699 bool success = true;
700 for (size_t i = 0; i < num_regexes; i++) {
701 std::string command = break_regexes[i][1];
702 command += " -o 1";
703 success =
704 tbreak_regex_cmd_up->AddRegexCommand(break_regexes[i][0], command);
705 if (!success)
706 break;
707 }
708 success =
709 tbreak_regex_cmd_up->AddRegexCommand("^$", "breakpoint list --full");
710
711 if (success) {
712 CommandObjectSP tbreak_regex_cmd_sp(tbreak_regex_cmd_up.release());
713 m_command_dict[std::string(tbreak_regex_cmd_sp->GetCommandName())] =
714 tbreak_regex_cmd_sp;
715 }
716 }
717
718 std::unique_ptr<CommandObjectRegexCommand> attach_regex_cmd_up(
720 *this, "_regexp-attach", "Attach to process by ID or name.",
721 "_regexp-attach <pid> | <process-name>", 0, false));
722 if (attach_regex_cmd_up) {
723 if (attach_regex_cmd_up->AddRegexCommand("^([0-9]+)[[:space:]]*$",
724 "process attach --pid %1") &&
725 attach_regex_cmd_up->AddRegexCommand(
726 "^(-.*|.* -.*)$", "process attach %1") && // Any options that are
727 // specified get passed to
728 // 'process attach'
729 attach_regex_cmd_up->AddRegexCommand("^(.+)$",
730 "process attach --name '%1'") &&
731 attach_regex_cmd_up->AddRegexCommand("^$", "process attach")) {
732 CommandObjectSP attach_regex_cmd_sp(attach_regex_cmd_up.release());
733 m_command_dict[std::string(attach_regex_cmd_sp->GetCommandName())] =
734 attach_regex_cmd_sp;
735 }
736 }
737
738 std::unique_ptr<CommandObjectRegexCommand> down_regex_cmd_up(
739 new CommandObjectRegexCommand(*this, "_regexp-down",
740 "Select a newer stack frame. Defaults to "
741 "moving one frame, a numeric argument can "
742 "specify an arbitrary number.",
743 "_regexp-down [<count>]", 0, false));
744 if (down_regex_cmd_up) {
745 if (down_regex_cmd_up->AddRegexCommand("^$", "frame select -r -1") &&
746 down_regex_cmd_up->AddRegexCommand("^([0-9]+)$",
747 "frame select -r -%1")) {
748 CommandObjectSP down_regex_cmd_sp(down_regex_cmd_up.release());
749 m_command_dict[std::string(down_regex_cmd_sp->GetCommandName())] =
750 down_regex_cmd_sp;
751 }
752 }
753
754 std::unique_ptr<CommandObjectRegexCommand> up_regex_cmd_up(
756 *this, "_regexp-up",
757 "Select an older stack frame. Defaults to moving one "
758 "frame, a numeric argument can specify an arbitrary number.",
759 "_regexp-up [<count>]", 0, false));
760 if (up_regex_cmd_up) {
761 if (up_regex_cmd_up->AddRegexCommand("^$", "frame select -r 1") &&
762 up_regex_cmd_up->AddRegexCommand("^([0-9]+)$", "frame select -r %1")) {
763 CommandObjectSP up_regex_cmd_sp(up_regex_cmd_up.release());
764 m_command_dict[std::string(up_regex_cmd_sp->GetCommandName())] =
765 up_regex_cmd_sp;
766 }
767 }
768
769 std::unique_ptr<CommandObjectRegexCommand> display_regex_cmd_up(
771 *this, "_regexp-display",
772 "Evaluate an expression at every stop (see 'help target stop-hook'.)",
773 "_regexp-display expression", 0, false));
774 if (display_regex_cmd_up) {
775 if (display_regex_cmd_up->AddRegexCommand(
776 "^(.+)$", "target stop-hook add -o \"expr -- %1\"")) {
777 CommandObjectSP display_regex_cmd_sp(display_regex_cmd_up.release());
778 m_command_dict[std::string(display_regex_cmd_sp->GetCommandName())] =
779 display_regex_cmd_sp;
780 }
781 }
782
783 std::unique_ptr<CommandObjectRegexCommand> undisplay_regex_cmd_up(
784 new CommandObjectRegexCommand(*this, "_regexp-undisplay",
785 "Stop displaying expression at every "
786 "stop (specified by stop-hook index.)",
787 "_regexp-undisplay stop-hook-number", 0,
788 false));
789 if (undisplay_regex_cmd_up) {
790 if (undisplay_regex_cmd_up->AddRegexCommand("^([0-9]+)$",
791 "target stop-hook delete %1")) {
792 CommandObjectSP undisplay_regex_cmd_sp(undisplay_regex_cmd_up.release());
793 m_command_dict[std::string(undisplay_regex_cmd_sp->GetCommandName())] =
794 undisplay_regex_cmd_sp;
795 }
796 }
797
798 std::unique_ptr<CommandObjectRegexCommand> connect_gdb_remote_cmd_up(
800 *this, "gdb-remote",
801 "Connect to a process via remote GDB server.\n"
802 "If no host is specified, localhost is assumed.\n"
803 "gdb-remote is an abbreviation for 'process connect --plugin "
804 "gdb-remote connect://<hostname>:<port>'\n",
805 "gdb-remote [<hostname>:]<portnum>", 0, false));
806 if (connect_gdb_remote_cmd_up) {
807 if (connect_gdb_remote_cmd_up->AddRegexCommand(
808 "^([^:]+|\\[[0-9a-fA-F:]+.*\\]):([0-9]+)$",
809 "process connect --plugin gdb-remote connect://%1:%2") &&
810 connect_gdb_remote_cmd_up->AddRegexCommand(
811 "^([[:digit:]]+)$",
812 "process connect --plugin gdb-remote connect://localhost:%1")) {
813 CommandObjectSP command_sp(connect_gdb_remote_cmd_up.release());
814 m_command_dict[std::string(command_sp->GetCommandName())] = command_sp;
815 }
816 }
817
818 std::unique_ptr<CommandObjectRegexCommand> connect_kdp_remote_cmd_up(
820 *this, "kdp-remote",
821 "Connect to a process via remote KDP server.\n"
822 "If no UDP port is specified, port 41139 is assumed.\n"
823 "kdp-remote is an abbreviation for 'process connect --plugin "
824 "kdp-remote udp://<hostname>:<port>'\n",
825 "kdp-remote <hostname>[:<portnum>]", 0, false));
826 if (connect_kdp_remote_cmd_up) {
827 if (connect_kdp_remote_cmd_up->AddRegexCommand(
828 "^([^:]+:[[:digit:]]+)$",
829 "process connect --plugin kdp-remote udp://%1") &&
830 connect_kdp_remote_cmd_up->AddRegexCommand(
831 "^(.+)$", "process connect --plugin kdp-remote udp://%1:41139")) {
832 CommandObjectSP command_sp(connect_kdp_remote_cmd_up.release());
833 m_command_dict[std::string(command_sp->GetCommandName())] = command_sp;
834 }
835 }
836
837 std::unique_ptr<CommandObjectRegexCommand> bt_regex_cmd_up(
839 *this, "_regexp-bt",
840 "Show backtrace of the current thread's call stack. Any numeric "
841 "argument displays at most that many frames. The argument 'all' "
842 "displays all threads. Use 'settings set frame-format' to customize "
843 "the printing of individual frames and 'settings set thread-format' "
844 "to customize the thread header. Frame recognizers may filter the "
845 "list. Use 'thread backtrace -u (--unfiltered)' to see them all.",
846 "bt [<digit> | all]", 0, false));
847 if (bt_regex_cmd_up) {
848 // accept but don't document "bt -c <number>" -- before bt was a regex
849 // command if you wanted to backtrace three frames you would do "bt -c 3"
850 // but the intention is to have this emulate the gdb "bt" command and so
851 // now "bt 3" is the preferred form, in line with gdb.
852 if (bt_regex_cmd_up->AddRegexCommand("^([[:digit:]]+)[[:space:]]*$",
853 "thread backtrace -c %1") &&
854 bt_regex_cmd_up->AddRegexCommand("^(-[^[:space:]].*)$", "thread backtrace %1") &&
855 bt_regex_cmd_up->AddRegexCommand("^all[[:space:]]*$", "thread backtrace all") &&
856 bt_regex_cmd_up->AddRegexCommand("^[[:space:]]*$", "thread backtrace")) {
857 CommandObjectSP command_sp(bt_regex_cmd_up.release());
858 m_command_dict[std::string(command_sp->GetCommandName())] = command_sp;
859 }
860 }
861
862 std::unique_ptr<CommandObjectRegexCommand> list_regex_cmd_up(
864 *this, "_regexp-list",
865 "List relevant source code using one of several shorthand formats.",
866 "\n"
867 "_regexp-list <file>:<line> // List around specific file/line\n"
868 "_regexp-list <line> // List current file around specified "
869 "line\n"
870 "_regexp-list <function-name> // List specified function\n"
871 "_regexp-list 0x<address> // List around specified address\n"
872 "_regexp-list -[<count>] // List previous <count> lines\n"
873 "_regexp-list // List subsequent lines",
875 if (list_regex_cmd_up) {
876 if (list_regex_cmd_up->AddRegexCommand("^([0-9]+)[[:space:]]*$",
877 "source list --line %1") &&
878 list_regex_cmd_up->AddRegexCommand(
879 "^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]"
880 "]*$",
881 "source list --file '%1' --line %2") &&
882 list_regex_cmd_up->AddRegexCommand(
883 "^\\*?(0x[[:xdigit:]]+)[[:space:]]*$",
884 "source list --address %1") &&
885 list_regex_cmd_up->AddRegexCommand("^-[[:space:]]*$",
886 "source list --reverse") &&
887 list_regex_cmd_up->AddRegexCommand(
888 "^-([[:digit:]]+)[[:space:]]*$",
889 "source list --reverse --count %1") &&
890 list_regex_cmd_up->AddRegexCommand("^(.+)$",
891 "source list --name \"%1\"") &&
892 list_regex_cmd_up->AddRegexCommand("^$", "source list")) {
893 CommandObjectSP list_regex_cmd_sp(list_regex_cmd_up.release());
894 m_command_dict[std::string(list_regex_cmd_sp->GetCommandName())] =
895 list_regex_cmd_sp;
896 }
897 }
898
899 std::unique_ptr<CommandObjectRegexCommand> env_regex_cmd_up(
901 *this, "_regexp-env",
902 "Shorthand for viewing and setting environment variables.",
903 "\n"
904 "_regexp-env // Show environment\n"
905 "_regexp-env <name>=<value> // Set an environment variable",
906 0, false));
907 if (env_regex_cmd_up) {
908 if (env_regex_cmd_up->AddRegexCommand("^$",
909 "settings show target.env-vars") &&
910 env_regex_cmd_up->AddRegexCommand("^([A-Za-z_][A-Za-z_0-9]*=.*)$",
911 "settings set target.env-vars %1")) {
912 CommandObjectSP env_regex_cmd_sp(env_regex_cmd_up.release());
913 m_command_dict[std::string(env_regex_cmd_sp->GetCommandName())] =
914 env_regex_cmd_sp;
915 }
916 }
917
918 std::unique_ptr<CommandObjectRegexCommand> jump_regex_cmd_up(
920 *this, "_regexp-jump", "Set the program counter to a new address.",
921 "\n"
922 "_regexp-jump <line>\n"
923 "_regexp-jump +<line-offset> | -<line-offset>\n"
924 "_regexp-jump <file>:<line>\n"
925 "_regexp-jump *<addr>\n",
926 0, false));
927 if (jump_regex_cmd_up) {
928 if (jump_regex_cmd_up->AddRegexCommand("^\\*(.*)$",
929 "thread jump --addr %1") &&
930 jump_regex_cmd_up->AddRegexCommand("^([0-9]+)$",
931 "thread jump --line %1") &&
932 jump_regex_cmd_up->AddRegexCommand("^([^:]+):([0-9]+)$",
933 "thread jump --file %1 --line %2") &&
934 jump_regex_cmd_up->AddRegexCommand("^([+\\-][0-9]+)$",
935 "thread jump --by %1")) {
936 CommandObjectSP jump_regex_cmd_sp(jump_regex_cmd_up.release());
937 m_command_dict[std::string(jump_regex_cmd_sp->GetCommandName())] =
938 jump_regex_cmd_sp;
939 }
940 }
941}
942
944 const char *cmd_str, bool include_aliases, StringList &matches,
945 StringList &descriptions) {
947 &descriptions);
948
949 if (include_aliases) {
951 &descriptions);
952 }
953
954 return matches.GetSize();
955}
956
958 Args &path, bool leaf_is_command, Status &result) {
959 result.Clear();
960
961 auto get_multi_or_report_error =
962 [&result](CommandObjectSP cmd_sp,
963 const char *name) -> CommandObjectMultiword * {
964 if (!cmd_sp) {
966 "Path component: '%s' not found", name);
967 return nullptr;
968 }
969 if (!cmd_sp->IsUserCommand()) {
971 "Path component: '%s' is not a user "
972 "command",
973 name);
974 return nullptr;
975 }
976 CommandObjectMultiword *cmd_as_multi = cmd_sp->GetAsMultiwordCommand();
977 if (!cmd_as_multi) {
979 "Path component: '%s' is not a container "
980 "command",
981 name);
982 return nullptr;
983 }
984 return cmd_as_multi;
985 };
986
987 size_t num_args = path.GetArgumentCount();
988 if (num_args == 0) {
989 result = Status::FromErrorString("empty command path");
990 return nullptr;
991 }
992
993 if (num_args == 1 && leaf_is_command) {
994 // We just got a leaf command to be added to the root. That's not an error,
995 // just return null for the container.
996 return nullptr;
997 }
998
999 // Start by getting the root command from the interpreter.
1000 const char *cur_name = path.GetArgumentAtIndex(0);
1001 CommandObjectSP cur_cmd_sp = GetCommandSPExact(cur_name);
1002 CommandObjectMultiword *cur_as_multi =
1003 get_multi_or_report_error(cur_cmd_sp, cur_name);
1004 if (cur_as_multi == nullptr)
1005 return nullptr;
1006
1007 size_t num_path_elements = num_args - (leaf_is_command ? 1 : 0);
1008 for (size_t cursor = 1; cursor < num_path_elements && cur_as_multi != nullptr;
1009 cursor++) {
1010 cur_name = path.GetArgumentAtIndex(cursor);
1011 cur_cmd_sp = cur_as_multi->GetSubcommandSPExact(cur_name);
1012 cur_as_multi = get_multi_or_report_error(cur_cmd_sp, cur_name);
1013 }
1014 return cur_as_multi;
1015}
1016
1018CommandInterpreter::GetCommandSP(llvm::StringRef cmd_str, bool include_aliases,
1019 bool exact, StringList *matches,
1020 StringList *descriptions) const {
1021 CommandObjectSP command_sp;
1022
1023 std::string cmd = std::string(cmd_str);
1024
1025 if (HasCommands()) {
1026 auto pos = m_command_dict.find(cmd);
1027 if (pos != m_command_dict.end())
1028 command_sp = pos->second;
1029 }
1030
1031 if (include_aliases && HasAliases()) {
1032 auto alias_pos = m_alias_dict.find(cmd);
1033 if (alias_pos != m_alias_dict.end())
1034 command_sp = alias_pos->second;
1035 }
1036
1037 if (HasUserCommands()) {
1038 auto pos = m_user_dict.find(cmd);
1039 if (pos != m_user_dict.end())
1040 command_sp = pos->second;
1041 }
1042
1044 auto pos = m_user_mw_dict.find(cmd);
1045 if (pos != m_user_mw_dict.end())
1046 command_sp = pos->second;
1047 }
1048
1049 if (!exact && !command_sp) {
1050 // We will only get into here if we didn't find any exact matches.
1051
1052 CommandObjectSP user_match_sp, user_mw_match_sp, alias_match_sp,
1053 real_match_sp;
1054
1055 StringList local_matches;
1056 if (matches == nullptr)
1057 matches = &local_matches;
1058
1059 unsigned int num_cmd_matches = 0;
1060 unsigned int num_alias_matches = 0;
1061 unsigned int num_user_matches = 0;
1062 unsigned int num_user_mw_matches = 0;
1063
1064 // Look through the command dictionaries one by one, and if we get only one
1065 // match from any of them in toto, then return that, otherwise return an
1066 // empty CommandObjectSP and the list of matches.
1067
1068 if (HasCommands()) {
1069 num_cmd_matches = AddNamesMatchingPartialString(m_command_dict, cmd_str,
1070 *matches, descriptions);
1071 }
1072
1073 if (num_cmd_matches == 1) {
1074 cmd.assign(matches->GetStringAtIndex(0));
1075 auto pos = m_command_dict.find(cmd);
1076 if (pos != m_command_dict.end())
1077 real_match_sp = pos->second;
1078 }
1079
1080 if (include_aliases && HasAliases()) {
1081 num_alias_matches = AddNamesMatchingPartialString(m_alias_dict, cmd_str,
1082 *matches, descriptions);
1083 }
1084
1085 if (num_alias_matches == 1) {
1086 cmd.assign(matches->GetStringAtIndex(num_cmd_matches));
1087 auto alias_pos = m_alias_dict.find(cmd);
1088 if (alias_pos != m_alias_dict.end())
1089 alias_match_sp = alias_pos->second;
1090 }
1091
1092 if (HasUserCommands()) {
1093 num_user_matches = AddNamesMatchingPartialString(m_user_dict, cmd_str,
1094 *matches, descriptions);
1095 }
1096
1097 if (num_user_matches == 1) {
1098 cmd.assign(
1099 matches->GetStringAtIndex(num_cmd_matches + num_alias_matches));
1100
1101 auto pos = m_user_dict.find(cmd);
1102 if (pos != m_user_dict.end())
1103 user_match_sp = pos->second;
1104 }
1105
1107 num_user_mw_matches = AddNamesMatchingPartialString(
1108 m_user_mw_dict, cmd_str, *matches, descriptions);
1109 }
1110
1111 if (num_user_mw_matches == 1) {
1112 cmd.assign(matches->GetStringAtIndex(num_cmd_matches + num_alias_matches +
1113 num_user_matches));
1114
1115 auto pos = m_user_mw_dict.find(cmd);
1116 if (pos != m_user_mw_dict.end())
1117 user_mw_match_sp = pos->second;
1118 }
1119
1120 // If we got exactly one match, return that, otherwise return the match
1121 // list.
1122
1123 if (num_user_matches + num_user_mw_matches + num_cmd_matches +
1124 num_alias_matches ==
1125 1) {
1126 if (num_cmd_matches)
1127 return real_match_sp;
1128 else if (num_alias_matches)
1129 return alias_match_sp;
1130 else if (num_user_mw_matches)
1131 return user_mw_match_sp;
1132 else
1133 return user_match_sp;
1134 }
1135 } else if (matches && command_sp) {
1136 matches->AppendString(cmd_str);
1137 if (descriptions)
1138 descriptions->AppendString(command_sp->GetHelp());
1139 }
1140
1141 return command_sp;
1142}
1143
1144bool CommandInterpreter::AddCommand(llvm::StringRef name,
1145 const lldb::CommandObjectSP &cmd_sp,
1146 bool can_replace) {
1147 if (cmd_sp.get())
1148 lldbassert((this == &cmd_sp->GetCommandInterpreter()) &&
1149 "tried to add a CommandObject from a different interpreter");
1150
1151 if (name.empty())
1152 return false;
1153
1154 cmd_sp->SetIsUserCommand(false);
1155
1156 std::string name_sstr(name);
1157 auto name_iter = m_command_dict.find(name_sstr);
1158 if (name_iter != m_command_dict.end()) {
1159 if (!can_replace || !name_iter->second->IsRemovable())
1160 return false;
1161 name_iter->second = cmd_sp;
1162 } else {
1163 m_command_dict[name_sstr] = cmd_sp;
1164 }
1165 return true;
1166}
1167
1169 const lldb::CommandObjectSP &cmd_sp,
1170 bool can_replace) {
1171 Status result;
1172 if (cmd_sp.get())
1173 lldbassert((this == &cmd_sp->GetCommandInterpreter()) &&
1174 "tried to add a CommandObject from a different interpreter");
1175 if (name.empty()) {
1176 result = Status::FromErrorString(
1177 "can't use the empty string for a command name");
1178 return result;
1179 }
1180 // do not allow replacement of internal commands
1181 if (CommandExists(name)) {
1182 result = Status::FromErrorString("can't replace builtin command");
1183 return result;
1184 }
1185
1186 if (UserCommandExists(name)) {
1187 if (!can_replace) {
1189 "user command \"{0}\" already exists and force replace was not set "
1190 "by --overwrite or 'settings set interpreter.require-overwrite "
1191 "false'",
1192 name);
1193 return result;
1194 }
1195 if (cmd_sp->IsMultiwordObject()) {
1196 if (!m_user_mw_dict[std::string(name)]->IsRemovable()) {
1197 result = Status::FromErrorString(
1198 "can't replace explicitly non-removable multi-word command");
1199 return result;
1200 }
1201 } else {
1202 if (!m_user_dict[std::string(name)]->IsRemovable()) {
1203 result = Status::FromErrorString(
1204 "can't replace explicitly non-removable command");
1205 return result;
1206 }
1207 }
1208 }
1209
1210 cmd_sp->SetIsUserCommand(true);
1211
1212 if (cmd_sp->IsMultiwordObject())
1213 m_user_mw_dict[std::string(name)] = cmd_sp;
1214 else
1215 m_user_dict[std::string(name)] = cmd_sp;
1216 return result;
1217}
1218
1221 bool include_aliases) const {
1222 // Break up the command string into words, in case it's a multi-word command.
1223 Args cmd_words(cmd_str);
1224
1225 if (cmd_str.empty())
1226 return {};
1227
1228 if (cmd_words.GetArgumentCount() == 1)
1229 return GetCommandSP(cmd_str, include_aliases, true);
1230
1231 // We have a multi-word command (seemingly), so we need to do more work.
1232 // First, get the cmd_obj_sp for the first word in the command.
1233 CommandObjectSP cmd_obj_sp =
1234 GetCommandSP(cmd_words.GetArgumentAtIndex(0), include_aliases, true);
1235 if (!cmd_obj_sp)
1236 return {};
1237
1238 // Loop through the rest of the words in the command (everything passed in
1239 // was supposed to be part of a command name), and find the appropriate
1240 // sub-command SP for each command word....
1241 size_t end = cmd_words.GetArgumentCount();
1242 for (size_t i = 1; i < end; ++i) {
1243 if (!cmd_obj_sp->IsMultiwordObject()) {
1244 // We have more words in the command name, but we don't have a
1245 // multiword object. Fail and return.
1246 return {};
1247 }
1248
1249 cmd_obj_sp = cmd_obj_sp->GetSubcommandSP(cmd_words.GetArgumentAtIndex(i));
1250 if (!cmd_obj_sp) {
1251 // The sub-command name was invalid. Fail and return.
1252 return {};
1253 }
1254 }
1255
1256 // We successfully looped through all the command words and got valid
1257 // command objects for them.
1258 return cmd_obj_sp;
1259}
1260
1263 StringList *matches,
1264 StringList *descriptions) const {
1265 // Try to find a match among commands and aliases. Allowing inexact matches,
1266 // but perferring exact matches.
1267 return GetCommandSP(cmd_str, /*include_aliases=*/true, /*exact=*/false,
1268 matches, descriptions)
1269 .get();
1270}
1271
1273 llvm::StringRef cmd, StringList *matches, StringList *descriptions) const {
1274 std::string cmd_str(cmd);
1275 auto find_exact = [&](const CommandObject::CommandMap &map) {
1276 auto found_elem = map.find(cmd);
1277 if (found_elem == map.end())
1278 return (CommandObject *)nullptr;
1279 CommandObject *exact_cmd = found_elem->second.get();
1280 if (exact_cmd) {
1281 if (matches)
1282 matches->AppendString(exact_cmd->GetCommandName());
1283 if (descriptions)
1284 descriptions->AppendString(exact_cmd->GetHelp());
1285 return exact_cmd;
1286 }
1287 return (CommandObject *)nullptr;
1288 };
1289
1290 CommandObject *exact_cmd = find_exact(GetUserCommands());
1291 if (exact_cmd)
1292 return exact_cmd;
1293
1294 exact_cmd = find_exact(GetUserMultiwordCommands());
1295 if (exact_cmd)
1296 return exact_cmd;
1297
1298 // We didn't have an exact command, so now look for partial matches.
1299 StringList tmp_list;
1300 StringList *matches_ptr = matches ? matches : &tmp_list;
1301 AddNamesMatchingPartialString(GetUserCommands(), cmd_str, *matches_ptr);
1303 cmd_str, *matches_ptr);
1304
1305 return {};
1306}
1307
1309 llvm::StringRef cmd, StringList *matches, StringList *descriptions) const {
1310 auto find_exact =
1311 [&](const CommandObject::CommandMap &map) -> CommandObject * {
1312 auto found_elem = map.find(cmd);
1313 if (found_elem == map.end())
1314 return (CommandObject *)nullptr;
1315 CommandObject *exact_cmd = found_elem->second.get();
1316 if (!exact_cmd)
1317 return nullptr;
1318
1319 if (matches)
1320 matches->AppendString(exact_cmd->GetCommandName());
1321
1322 if (descriptions)
1323 descriptions->AppendString(exact_cmd->GetHelp());
1324
1325 return exact_cmd;
1326 return nullptr;
1327 };
1328
1329 CommandObject *exact_cmd = find_exact(GetAliases());
1330 if (exact_cmd)
1331 return exact_cmd;
1332
1333 // We didn't have an exact command, so now look for partial matches.
1334 StringList tmp_list;
1335 StringList *matches_ptr = matches ? matches : &tmp_list;
1336 AddNamesMatchingPartialString(GetAliases(), cmd, *matches_ptr);
1337
1338 return {};
1339}
1340
1341bool CommandInterpreter::CommandExists(llvm::StringRef cmd) const {
1342 return m_command_dict.find(cmd) != m_command_dict.end();
1343}
1344
1346 std::string &full_name) const {
1347 bool exact_match = (m_alias_dict.find(cmd) != m_alias_dict.end());
1348 if (exact_match) {
1349 full_name.assign(std::string(cmd));
1350 return exact_match;
1351 } else {
1352 StringList matches;
1353 size_t num_alias_matches;
1354 num_alias_matches =
1356 if (num_alias_matches == 1) {
1357 // Make sure this isn't shadowing a command in the regular command space:
1358 StringList regular_matches;
1359 const bool include_aliases = false;
1360 const bool exact = false;
1361 CommandObjectSP cmd_obj_sp(
1362 GetCommandSP(cmd, include_aliases, exact, &regular_matches));
1363 if (cmd_obj_sp || regular_matches.GetSize() > 0)
1364 return false;
1365 else {
1366 full_name.assign(matches.GetStringAtIndex(0));
1367 return true;
1368 }
1369 } else
1370 return false;
1371 }
1372}
1373
1374bool CommandInterpreter::AliasExists(llvm::StringRef cmd) const {
1375 return m_alias_dict.find(cmd) != m_alias_dict.end();
1376}
1377
1378bool CommandInterpreter::UserCommandExists(llvm::StringRef cmd) const {
1379 return m_user_dict.find(cmd) != m_user_dict.end();
1380}
1381
1382bool CommandInterpreter::UserMultiwordCommandExists(llvm::StringRef cmd) const {
1383 return m_user_mw_dict.find(cmd) != m_user_mw_dict.end();
1384}
1385
1387CommandInterpreter::AddAlias(llvm::StringRef alias_name,
1388 lldb::CommandObjectSP &command_obj_sp,
1389 llvm::StringRef args_string) {
1390 if (command_obj_sp.get())
1391 lldbassert((this == &command_obj_sp->GetCommandInterpreter()) &&
1392 "tried to add a CommandObject from a different interpreter");
1393
1394 std::unique_ptr<CommandAlias> command_alias_up(
1395 new CommandAlias(*this, command_obj_sp, args_string, alias_name));
1396
1397 if (command_alias_up && command_alias_up->IsValid()) {
1398 m_alias_dict[std::string(alias_name)] =
1399 CommandObjectSP(command_alias_up.get());
1400 return command_alias_up.release();
1401 }
1402
1403 return nullptr;
1404}
1405
1406bool CommandInterpreter::RemoveAlias(llvm::StringRef alias_name) {
1407 auto pos = m_alias_dict.find(alias_name);
1408 if (pos != m_alias_dict.end()) {
1409 m_alias_dict.erase(pos);
1410 return true;
1411 }
1412 return false;
1413}
1414
1415bool CommandInterpreter::RemoveCommand(llvm::StringRef cmd, bool force) {
1416 auto pos = m_command_dict.find(cmd);
1417 if (pos != m_command_dict.end()) {
1418 if (force || pos->second->IsRemovable()) {
1419 // Only regular expression objects or python commands are removable under
1420 // normal circumstances.
1421 m_command_dict.erase(pos);
1422 return true;
1423 }
1424 }
1425 return false;
1426}
1427
1428bool CommandInterpreter::RemoveUser(llvm::StringRef user_name) {
1429 CommandObject::CommandMap::iterator pos = m_user_dict.find(user_name);
1430 if (pos != m_user_dict.end()) {
1431 m_user_dict.erase(pos);
1432 return true;
1433 }
1434 return false;
1435}
1436
1437bool CommandInterpreter::RemoveUserMultiword(llvm::StringRef multi_name) {
1438 CommandObject::CommandMap::iterator pos = m_user_mw_dict.find(multi_name);
1439 if (pos != m_user_mw_dict.end()) {
1440 m_user_mw_dict.erase(pos);
1441 return true;
1442 }
1443 return false;
1444}
1445
1447 uint32_t cmd_types) {
1448 llvm::StringRef help_prologue(GetDebugger().GetIOHandlerHelpPrologue());
1449 if (!help_prologue.empty()) {
1450 OutputFormattedHelpText(result.GetOutputStream(), llvm::StringRef(),
1451 help_prologue);
1452 }
1453
1454 CommandObject::CommandMap::const_iterator pos;
1455 size_t max_len = FindLongestCommandWord(m_command_dict);
1456
1457 if ((cmd_types & eCommandTypesBuiltin) == eCommandTypesBuiltin) {
1458 result.AppendMessage("Debugger commands:");
1459 result.AppendMessage("");
1460
1461 for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos) {
1462 if (!(cmd_types & eCommandTypesHidden) &&
1463 (pos->first.compare(0, 1, "_") == 0))
1464 continue;
1465
1466 OutputFormattedHelpText(result.GetOutputStream(), pos->first, "--",
1467 pos->second->GetHelp(), max_len);
1468 }
1469 result.AppendMessage("");
1470 }
1471
1472 if (!m_alias_dict.empty() &&
1473 ((cmd_types & eCommandTypesAliases) == eCommandTypesAliases)) {
1475 "Current command abbreviations "
1476 "(type '%shelp command alias' for more info):\n",
1478 result.AppendMessage("");
1480
1481 for (auto alias_pos = m_alias_dict.begin(); alias_pos != m_alias_dict.end();
1482 ++alias_pos) {
1483 OutputFormattedHelpText(result.GetOutputStream(), alias_pos->first, "--",
1484 alias_pos->second->GetHelp(), max_len);
1485 }
1486 result.AppendMessage("");
1487 }
1488
1489 if (!m_user_dict.empty() &&
1490 ((cmd_types & eCommandTypesUserDef) == eCommandTypesUserDef)) {
1491 result.AppendMessage("Current user-defined commands:");
1492 result.AppendMessage("");
1494 for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos) {
1495 OutputFormattedHelpText(result.GetOutputStream(), pos->first, "--",
1496 pos->second->GetHelp(), max_len);
1497 }
1498 result.AppendMessage("");
1499 }
1500
1501 if (!m_user_mw_dict.empty() &&
1502 ((cmd_types & eCommandTypesUserMW) == eCommandTypesUserMW)) {
1503 result.AppendMessage("Current user-defined container commands:");
1504 result.AppendMessage("");
1506 for (pos = m_user_mw_dict.begin(); pos != m_user_mw_dict.end(); ++pos) {
1507 OutputFormattedHelpText(result.GetOutputStream(), pos->first, "--",
1508 pos->second->GetHelp(), max_len);
1509 }
1510 result.AppendMessage("");
1511 }
1512
1514 "For more information on any command, type '%shelp <command-name>'.\n",
1516}
1517
1519 llvm::StringRef &command_string) {
1520 // This function finds the final, lowest-level, alias-resolved command object
1521 // whose 'Execute' function will eventually be invoked by the given command
1522 // line.
1523
1524 CommandObject *cmd_obj = nullptr;
1525 size_t start = command_string.find_first_not_of(k_white_space);
1526 size_t end = 0;
1527 bool done = false;
1528 while (!done) {
1529 if (start != std::string::npos) {
1530 // Get the next word from command_string.
1531 end = command_string.find_first_of(k_white_space, start);
1532 if (end == std::string::npos)
1533 end = command_string.size();
1534 std::string cmd_word =
1535 std::string(command_string.substr(start, end - start));
1536
1537 if (cmd_obj == nullptr)
1538 // Since cmd_obj is NULL we are on our first time through this loop.
1539 // Check to see if cmd_word is a valid command or alias.
1540 cmd_obj = GetCommandObject(cmd_word);
1541 else if (cmd_obj->IsMultiwordObject()) {
1542 // Our current object is a multi-word object; see if the cmd_word is a
1543 // valid sub-command for our object.
1544 CommandObject *sub_cmd_obj =
1545 cmd_obj->GetSubcommandObject(cmd_word.c_str());
1546 if (sub_cmd_obj)
1547 cmd_obj = sub_cmd_obj;
1548 else // cmd_word was not a valid sub-command word, so we are done
1549 done = true;
1550 } else
1551 // We have a cmd_obj and it is not a multi-word object, so we are done.
1552 done = true;
1553
1554 // If we didn't find a valid command object, or our command object is not
1555 // a multi-word object, or we are at the end of the command_string, then
1556 // we are done. Otherwise, find the start of the next word.
1557
1558 if (!cmd_obj || !cmd_obj->IsMultiwordObject() ||
1559 end >= command_string.size())
1560 done = true;
1561 else
1562 start = command_string.find_first_not_of(k_white_space, end);
1563 } else
1564 // Unable to find any more words.
1565 done = true;
1566 }
1567
1568 command_string = command_string.substr(end);
1569 return cmd_obj;
1570}
1571
1572static const char *k_valid_command_chars =
1573 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
1574static void StripLeadingSpaces(std::string &s) {
1575 if (!s.empty()) {
1576 size_t pos = s.find_first_not_of(k_white_space);
1577 if (pos == std::string::npos)
1578 s.clear();
1579 else if (pos == 0)
1580 return;
1581 s.erase(0, pos);
1582 }
1583}
1584
1585static size_t FindArgumentTerminator(const std::string &s) {
1586 const size_t s_len = s.size();
1587 size_t offset = 0;
1588 while (offset < s_len) {
1589 size_t pos = s.find("--", offset);
1590 if (pos == std::string::npos)
1591 break;
1592 if (pos > 0) {
1593 if (llvm::isSpace(s[pos - 1])) {
1594 // Check if the string ends "\s--" (where \s is a space character) or
1595 // if we have "\s--\s".
1596 if ((pos + 2 >= s_len) || llvm::isSpace(s[pos + 2])) {
1597 return pos;
1598 }
1599 }
1600 }
1601 offset = pos + 2;
1602 }
1603 return std::string::npos;
1604}
1605
1606static bool ExtractCommand(std::string &command_string, std::string &command,
1607 std::string &suffix, char &quote_char) {
1608 command.clear();
1609 suffix.clear();
1610 StripLeadingSpaces(command_string);
1611
1612 bool result = false;
1613 quote_char = '\0';
1614
1615 if (!command_string.empty()) {
1616 const char first_char = command_string[0];
1617 if (first_char == '\'' || first_char == '"') {
1618 quote_char = first_char;
1619 const size_t end_quote_pos = command_string.find(quote_char, 1);
1620 if (end_quote_pos == std::string::npos) {
1621 command.swap(command_string);
1622 command_string.erase();
1623 } else {
1624 command.assign(command_string, 1, end_quote_pos - 1);
1625 if (end_quote_pos + 1 < command_string.size())
1626 command_string.erase(0, command_string.find_first_not_of(
1627 k_white_space, end_quote_pos + 1));
1628 else
1629 command_string.erase();
1630 }
1631 } else {
1632 const size_t first_space_pos =
1633 command_string.find_first_of(k_white_space);
1634 if (first_space_pos == std::string::npos) {
1635 command.swap(command_string);
1636 command_string.erase();
1637 } else {
1638 command.assign(command_string, 0, first_space_pos);
1639 command_string.erase(0, command_string.find_first_not_of(
1640 k_white_space, first_space_pos));
1641 }
1642 }
1643 result = true;
1644 }
1645
1646 if (!command.empty()) {
1647 // actual commands can't start with '-' or '_'
1648 if (command[0] != '-' && command[0] != '_') {
1649 size_t pos = command.find_first_not_of(k_valid_command_chars);
1650 if (pos > 0 && pos != std::string::npos) {
1651 suffix.assign(command.begin() + pos, command.end());
1652 command.erase(pos);
1653 }
1654 }
1655 }
1656
1657 return result;
1658}
1659
1661 llvm::StringRef alias_name, std::string &raw_input_string,
1662 std::string &alias_result, CommandReturnObject &result) {
1663 CommandObject *alias_cmd_obj = nullptr;
1664 Args cmd_args(raw_input_string);
1665 alias_cmd_obj = GetCommandObject(alias_name);
1666 StreamString result_str;
1667
1668 if (!alias_cmd_obj || !alias_cmd_obj->IsAlias()) {
1669 alias_result.clear();
1670 return alias_cmd_obj;
1671 }
1672 std::pair<CommandObjectSP, OptionArgVectorSP> desugared =
1673 ((CommandAlias *)alias_cmd_obj)->Desugar();
1674 OptionArgVectorSP option_arg_vector_sp = desugared.second;
1675 alias_cmd_obj = desugared.first.get();
1676 std::string alias_name_str = std::string(alias_name);
1677 if ((cmd_args.GetArgumentCount() == 0) ||
1678 (alias_name_str != cmd_args.GetArgumentAtIndex(0)))
1679 cmd_args.Unshift(alias_name_str);
1680
1681 result_str.Printf("%s", alias_cmd_obj->GetCommandName().str().c_str());
1682
1683 if (!option_arg_vector_sp.get()) {
1684 alias_result = std::string(result_str.GetString());
1685 return alias_cmd_obj;
1686 }
1687 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
1688
1689 int value_type;
1690 std::string option;
1691 std::string value;
1692 for (const auto &entry : *option_arg_vector) {
1693 std::tie(option, value_type, value) = entry;
1694 if (option == g_argument) {
1695 result_str.Printf(" %s", value.c_str());
1696 continue;
1697 }
1698
1699 result_str.Printf(" %s", option.c_str());
1700 if (value_type == OptionParser::eNoArgument)
1701 continue;
1702
1703 if (value_type != OptionParser::eOptionalArgument)
1704 result_str.Printf(" ");
1705 int index = GetOptionArgumentPosition(value.c_str());
1706 if (index == 0)
1707 result_str.Printf("%s", value.c_str());
1708 else if (static_cast<size_t>(index) >= cmd_args.GetArgumentCount()) {
1709
1710 result.AppendErrorWithFormat("Not enough arguments provided; you "
1711 "need at least %d arguments to use "
1712 "this alias.\n",
1713 index);
1714 return nullptr;
1715 } else {
1716 const Args::ArgEntry &entry = cmd_args[index];
1717 size_t strpos = raw_input_string.find(entry.c_str());
1718 const char quote_char = entry.GetQuoteChar();
1719 if (strpos != std::string::npos) {
1720 const size_t start_fudge = quote_char == '\0' ? 0 : 1;
1721 const size_t len_fudge = quote_char == '\0' ? 0 : 2;
1722
1723 // Make sure we aren't going outside the bounds of the cmd string:
1724 if (strpos < start_fudge) {
1725 result.AppendError("Unmatched quote at command beginning.");
1726 return nullptr;
1727 }
1728 llvm::StringRef arg_text = entry.ref();
1729 if (strpos - start_fudge + arg_text.size() + len_fudge >
1730 raw_input_string.size()) {
1731 result.AppendError("Unmatched quote at command end.");
1732 return nullptr;
1733 }
1734 raw_input_string = raw_input_string.erase(
1735 strpos - start_fudge,
1736 strlen(cmd_args.GetArgumentAtIndex(index)) + len_fudge);
1737 }
1738 if (quote_char == '\0')
1739 result_str.Printf("%s", cmd_args.GetArgumentAtIndex(index));
1740 else
1741 result_str.Printf("%c%s%c", quote_char, entry.c_str(), quote_char);
1742 }
1743 }
1744
1745 alias_result = std::string(result_str.GetString());
1746 return alias_cmd_obj;
1747}
1748
1750 // The command preprocessor needs to do things to the command line before any
1751 // parsing of arguments or anything else is done. The only current stuff that
1752 // gets preprocessed is anything enclosed in backtick ('`') characters is
1753 // evaluated as an expression and the result of the expression must be a
1754 // scalar that can be substituted into the command. An example would be:
1755 // (lldb) memory read `$rsp + 20`
1756 Status error; // Status for any expressions that might not evaluate
1757 size_t start_backtick;
1758 size_t pos = 0;
1759 while ((start_backtick = command.find('`', pos)) != std::string::npos) {
1760 // Stop if an error was encountered during the previous iteration.
1761 if (error.Fail())
1762 break;
1763
1764 if (start_backtick > 0 && command[start_backtick - 1] == '\\') {
1765 // The backtick was preceded by a '\' character, remove the slash and
1766 // don't treat the backtick as the start of an expression.
1767 command.erase(start_backtick - 1, 1);
1768 // No need to add one to start_backtick since we just deleted a char.
1769 pos = start_backtick;
1770 continue;
1771 }
1772
1773 const size_t expr_content_start = start_backtick + 1;
1774 const size_t end_backtick = command.find('`', expr_content_start);
1775
1776 if (end_backtick == std::string::npos) {
1777 // Stop if there's no end backtick.
1778 break;
1779 }
1780
1781 if (end_backtick == expr_content_start) {
1782 // Skip over empty expression. (two backticks in a row)
1783 command.erase(start_backtick, 2);
1784 continue;
1785 }
1786
1787 std::string expr_str(command, expr_content_start,
1788 end_backtick - expr_content_start);
1789 error = PreprocessToken(expr_str);
1790 // We always stop at the first error:
1791 if (error.Fail())
1792 break;
1793
1794 command.erase(start_backtick, end_backtick - start_backtick + 1);
1795 command.insert(start_backtick, std::string(expr_str));
1796 pos = start_backtick + expr_str.size();
1797 }
1798 return error;
1799}
1800
1801Status
1803 Status error;
1805
1806 // Get a dummy target to allow for calculator mode while processing
1807 // backticks. This also helps break the infinite loop caused when target is
1808 // null.
1809 Target *exe_target = exe_ctx.GetTargetPtr();
1810 Target &target = exe_target ? *exe_target : m_debugger.GetDummyTarget();
1811
1812 ValueObjectSP expr_result_valobj_sp;
1813
1815 options.SetCoerceToId(false);
1816 options.SetUnwindOnError(true);
1817 options.SetIgnoreBreakpoints(true);
1818 options.SetKeepInMemory(false);
1819 options.SetTryAllThreads(true);
1820 options.SetTimeout(std::nullopt);
1821
1822 ExpressionResults expr_result =
1823 target.EvaluateExpression(expr_str.c_str(), exe_ctx.GetFramePtr(),
1824 expr_result_valobj_sp, options);
1825
1826 if (expr_result == eExpressionCompleted) {
1827 Scalar scalar;
1828 if (expr_result_valobj_sp)
1829 expr_result_valobj_sp =
1830 expr_result_valobj_sp->GetQualifiedRepresentationIfAvailable(
1831 expr_result_valobj_sp->GetDynamicValueType(), true);
1832 if (expr_result_valobj_sp->ResolveValue(scalar)) {
1833
1834 StreamString value_strm;
1835 const bool show_type = false;
1836 scalar.GetValue(value_strm, show_type);
1837 size_t value_string_size = value_strm.GetSize();
1838 if (value_string_size) {
1839 expr_str = value_strm.GetData();
1840 } else {
1841 error =
1842 Status::FromErrorStringWithFormat("expression value didn't result "
1843 "in a scalar value for the "
1844 "expression '%s'",
1845 expr_str.c_str());
1846 }
1847 } else {
1848 error =
1849 Status::FromErrorStringWithFormat("expression value didn't result "
1850 "in a scalar value for the "
1851 "expression '%s'",
1852 expr_str.c_str());
1853 }
1854 return error;
1855 }
1856
1857 // If we have an error from the expression evaluation it will be in the
1858 // ValueObject error, which won't be success and we will just report it.
1859 // But if for some reason we didn't get a value object at all, then we will
1860 // make up some helpful errors from the expression result.
1861 if (expr_result_valobj_sp)
1862 error = expr_result_valobj_sp->GetError().Clone();
1863
1864 if (error.Success()) {
1865 std::string result = lldb_private::toString(expr_result) +
1866 "for the expression '" + expr_str + "'";
1867 error = Status(result);
1868 }
1869 return error;
1870}
1871
1872bool CommandInterpreter::HandleCommand(const char *command_line,
1873 LazyBool lazy_add_to_history,
1874 const ExecutionContext &override_context,
1875 CommandReturnObject &result) {
1876
1877 OverrideExecutionContext(override_context);
1878 bool status = HandleCommand(command_line, lazy_add_to_history, result);
1880 return status;
1881}
1882
1883bool CommandInterpreter::HandleCommand(const char *command_line,
1884 LazyBool lazy_add_to_history,
1885 CommandReturnObject &result,
1886 bool force_repeat_command) {
1887 std::string command_string(command_line);
1888 std::string original_command_string(command_string);
1889 std::string real_original_command_string(command_string);
1890
1892 llvm::PrettyStackTraceFormat stack_trace("HandleCommand(command = \"%s\")",
1893 command_line);
1894
1895 LLDB_LOGF(log, "Processing command: %s", command_line);
1896 LLDB_SCOPED_TIMERF("Processing command: %s.", command_line);
1897
1898 if (INTERRUPT_REQUESTED(GetDebugger(), "Interrupted initiating command")) {
1899 result.AppendError("... Interrupted");
1900 return false;
1901 }
1902
1903 bool add_to_history;
1904 if (lazy_add_to_history == eLazyBoolCalculate)
1905 add_to_history = (m_command_source_depth == 0);
1906 else
1907 add_to_history = (lazy_add_to_history == eLazyBoolYes);
1908
1909 // The same `transcript_item` will be used below to add output and error of
1910 // the command.
1911 StructuredData::DictionarySP transcript_item;
1912 if (GetSaveTranscript()) {
1913 m_transcript_stream << "(lldb) " << command_line << '\n';
1914
1915 transcript_item = std::make_shared<StructuredData::Dictionary>();
1916 transcript_item->AddStringItem("command", command_line);
1917 transcript_item->AddIntegerItem(
1918 "timestampInEpochSeconds",
1919 std::chrono::duration_cast<std::chrono::seconds>(
1920 std::chrono::system_clock::now().time_since_epoch())
1921 .count());
1922 m_transcript.AddItem(transcript_item);
1923 }
1924
1925 bool empty_command = false;
1926 bool comment_command = false;
1927 if (command_string.empty())
1928 empty_command = true;
1929 else {
1930 const char *k_space_characters = "\t\n\v\f\r ";
1931
1932 size_t non_space = command_string.find_first_not_of(k_space_characters);
1933 // Check for empty line or comment line (lines whose first non-space
1934 // character is the comment character for this interpreter)
1935 if (non_space == std::string::npos)
1936 empty_command = true;
1937 else if (command_string[non_space] == m_comment_char)
1938 comment_command = true;
1939 else if (command_string[non_space] == CommandHistory::g_repeat_char) {
1940 llvm::StringRef search_str(command_string);
1941 search_str = search_str.drop_front(non_space);
1942 if (auto hist_str = m_command_history.FindString(search_str)) {
1943 add_to_history = false;
1944 command_string = std::string(*hist_str);
1945 original_command_string = std::string(*hist_str);
1946 } else {
1947 result.AppendErrorWithFormat("Could not find entry: %s in history",
1948 command_string.c_str());
1949 return false;
1950 }
1951 }
1952 }
1953
1954 if (empty_command) {
1955 if (!GetRepeatPreviousCommand()) {
1957 return true;
1958 }
1959
1960 if (m_command_history.IsEmpty()) {
1961 result.AppendError("empty command");
1962 return false;
1963 }
1964
1965 command_line = m_repeat_command.c_str();
1966 command_string = command_line;
1967 original_command_string = command_line;
1968 if (m_repeat_command.empty()) {
1969 result.AppendError("No auto repeat.");
1970 return false;
1971 }
1972
1973 add_to_history = false;
1974 } else if (comment_command) {
1976 return true;
1977 }
1978
1979 // Phase 1.
1980
1981 // Before we do ANY kind of argument processing, we need to figure out what
1982 // the real/final command object is for the specified command. This gets
1983 // complicated by the fact that the user could have specified an alias, and,
1984 // in translating the alias, there may also be command options and/or even
1985 // data (including raw text strings) that need to be found and inserted into
1986 // the command line as part of the translation. So this first step is plain
1987 // look-up and replacement, resulting in:
1988 // 1. the command object whose Execute method will actually be called
1989 // 2. a revised command string, with all substitutions and replacements
1990 // taken care of
1991 // From 1 above, we can determine whether the Execute function wants raw
1992 // input or not.
1993
1994 CommandObject *cmd_obj = ResolveCommandImpl(command_string, result);
1995
1996 // We have to preprocess the whole command string for Raw commands, since we
1997 // don't know the structure of the command. For parsed commands, we only
1998 // treat backticks as quote characters specially.
1999 // FIXME: We probably want to have raw commands do their own preprocessing.
2000 // For instance, I don't think people expect substitution in expr expressions.
2001 if (cmd_obj && cmd_obj->WantsRawCommandString()) {
2002 Status error(PreprocessCommand(command_string));
2003
2004 if (error.Fail()) {
2005 result.AppendError(error.AsCString());
2006 return false;
2007 }
2008 }
2009
2010 // Although the user may have abbreviated the command, the command_string now
2011 // has the command expanded to the full name. For example, if the input was
2012 // "br s -n main", command_string is now "breakpoint set -n main".
2013 if (log) {
2014 llvm::StringRef command_name = cmd_obj ? cmd_obj->GetCommandName() : "<not found>";
2015 LLDB_LOGF(log, "HandleCommand, cmd_obj : '%s'", command_name.str().c_str());
2016 LLDB_LOGF(log, "HandleCommand, (revised) command_string: '%s'",
2017 command_string.c_str());
2018 const bool wants_raw_input =
2019 (cmd_obj != nullptr) ? cmd_obj->WantsRawCommandString() : false;
2020 LLDB_LOGF(log, "HandleCommand, wants_raw_input:'%s'",
2021 wants_raw_input ? "True" : "False");
2022 }
2023
2024 // Phase 2.
2025 // Take care of things like setting up the history command & calling the
2026 // appropriate Execute method on the CommandObject, with the appropriate
2027 // arguments.
2028 StatsDuration execute_time;
2029 if (cmd_obj != nullptr) {
2030 bool generate_repeat_command = add_to_history;
2031 // If we got here when empty_command was true, then this command is a
2032 // stored "repeat command" which we should give a chance to produce it's
2033 // repeat command, even though we don't add repeat commands to the history.
2034 generate_repeat_command |= empty_command;
2035 // For `command regex`, the regex command (ex `bt`) is added to history, but
2036 // the resolved command (ex `thread backtrace`) is _not_ added to history.
2037 // However, the resolved command must be given the opportunity to provide a
2038 // repeat command. `force_repeat_command` supports this case.
2039 generate_repeat_command |= force_repeat_command;
2040 if (generate_repeat_command) {
2041 Args command_args(command_string);
2042 std::optional<std::string> repeat_command =
2043 cmd_obj->GetRepeatCommand(command_args, 0);
2044 if (repeat_command) {
2045 LLDB_LOGF(log, "Repeat command: %s", repeat_command->data());
2046 m_repeat_command.assign(*repeat_command);
2047 } else {
2048 m_repeat_command.assign(original_command_string);
2049 }
2050 }
2051
2052 if (add_to_history)
2053 m_command_history.AppendString(original_command_string);
2054
2055 std::string remainder;
2056 const std::size_t actual_cmd_name_len = cmd_obj->GetCommandName().size();
2057 if (actual_cmd_name_len < command_string.length())
2058 remainder = command_string.substr(actual_cmd_name_len);
2059
2060 // Remove any initial spaces
2061 size_t pos = remainder.find_first_not_of(k_white_space);
2062 if (pos != 0 && pos != std::string::npos)
2063 remainder.erase(0, pos);
2064
2065 LLDB_LOGF(
2066 log, "HandleCommand, command line after removing command name(s): '%s'",
2067 remainder.c_str());
2068
2069 // To test whether or not transcript should be saved, `transcript_item` is
2070 // used instead of `GetSaveTranscript()`. This is because the latter will
2071 // fail when the command is "settings set interpreter.save-transcript true".
2072 if (transcript_item) {
2073 transcript_item->AddStringItem("commandName", cmd_obj->GetCommandName());
2074 transcript_item->AddStringItem("commandArguments", remainder);
2075 }
2076
2077 ElapsedTime elapsed(execute_time);
2078 cmd_obj->SetOriginalCommandString(real_original_command_string);
2079 // Set the indent to the position of the command in the command line.
2080 pos = real_original_command_string.rfind(remainder);
2081 std::optional<uint16_t> indent;
2082 if (pos != std::string::npos)
2083 indent = pos;
2084 result.SetDiagnosticIndent(indent);
2085 cmd_obj->Execute(remainder.c_str(), result);
2086 }
2087
2088 LLDB_LOGF(log, "HandleCommand, command %s",
2089 (result.Succeeded() ? "succeeded" : "did not succeed"));
2090
2091 // To test whether or not transcript should be saved, `transcript_item` is
2092 // used instead of `GetSaveTrasncript()`. This is because the latter will
2093 // fail when the command is "settings set interpreter.save-transcript true".
2094 if (transcript_item) {
2097
2098 transcript_item->AddStringItem("output", result.GetOutputString());
2099 transcript_item->AddStringItem("error", result.GetErrorString());
2100 transcript_item->AddFloatItem("durationInSeconds",
2101 execute_time.get().count());
2102 }
2103
2104 return result.Succeeded();
2105}
2106
2108 bool look_for_subcommand = false;
2109
2110 // For any of the command completions a unique match will be a complete word.
2111
2112 if (request.GetParsedLine().GetArgumentCount() == 0) {
2113 // We got nothing on the command line, so return the list of commands
2114 bool include_aliases = true;
2115 StringList new_matches, descriptions;
2116 GetCommandNamesMatchingPartialString("", include_aliases, new_matches,
2117 descriptions);
2118 request.AddCompletions(new_matches, descriptions);
2119 } else if (request.GetCursorIndex() == 0) {
2120 // The cursor is in the first argument, so just do a lookup in the
2121 // dictionary.
2122 StringList new_matches, new_descriptions;
2123 CommandObject *cmd_obj =
2125 &new_matches, &new_descriptions);
2126
2127 if (new_matches.GetSize() && cmd_obj && cmd_obj->IsMultiwordObject() &&
2128 new_matches.GetStringAtIndex(0) != nullptr &&
2129 strcmp(request.GetParsedLine().GetArgumentAtIndex(0),
2130 new_matches.GetStringAtIndex(0)) == 0) {
2131 if (request.GetParsedLine().GetArgumentCount() != 1) {
2132 look_for_subcommand = true;
2133 new_matches.DeleteStringAtIndex(0);
2134 new_descriptions.DeleteStringAtIndex(0);
2135 request.AppendEmptyArgument();
2136 }
2137 }
2138 request.AddCompletions(new_matches, new_descriptions);
2139 }
2140
2141 if (request.GetCursorIndex() > 0 || look_for_subcommand) {
2142 // We are completing further on into a commands arguments, so find the
2143 // command and tell it to complete the command. First see if there is a
2144 // matching initial command:
2145 CommandObject *command_object =
2147 if (command_object) {
2148 request.ShiftArguments();
2149 command_object->HandleCompletion(request);
2150 }
2151 }
2152}
2153
2155
2156 // Don't complete comments, and if the line we are completing is just the
2157 // history repeat character, substitute the appropriate history line.
2158 llvm::StringRef first_arg = request.GetParsedLine().GetArgumentAtIndex(0);
2159
2160 if (!first_arg.empty()) {
2161 if (first_arg.front() == m_comment_char)
2162 return;
2163 if (first_arg.front() == CommandHistory::g_repeat_char) {
2164 if (auto hist_str = m_command_history.FindString(first_arg))
2165 request.AddCompletion(*hist_str, "Previous command history event",
2167 return;
2168 }
2169 }
2170
2171 HandleCompletionMatches(request);
2172}
2173
2174std::optional<std::string>
2176 if (line.empty())
2177 return std::nullopt;
2178 const size_t s = m_command_history.GetSize();
2179 for (int i = s - 1; i >= 0; --i) {
2180 llvm::StringRef entry = m_command_history.GetStringAtIndex(i);
2181 if (entry.consume_front(line))
2182 return entry.str();
2183 }
2184 return std::nullopt;
2185}
2186
2187void CommandInterpreter::UpdatePrompt(llvm::StringRef new_prompt) {
2188 EventSP prompt_change_event_sp(
2189 new Event(eBroadcastBitResetPrompt, new EventDataBytes(new_prompt)));
2190 ;
2191 BroadcastEvent(prompt_change_event_sp);
2193 m_command_io_handler_sp->SetPrompt(new_prompt);
2194}
2195
2196bool CommandInterpreter::Confirm(llvm::StringRef message, bool default_answer) {
2197 // Check AutoConfirm first:
2199 return default_answer;
2200
2201 IOHandlerConfirm *confirm =
2202 new IOHandlerConfirm(m_debugger, message, default_answer);
2203 IOHandlerSP io_handler_sp(confirm);
2204 m_debugger.RunIOHandlerSync(io_handler_sp);
2205 return confirm->GetResponse();
2206}
2207
2208const CommandAlias *
2209CommandInterpreter::GetAlias(llvm::StringRef alias_name) const {
2210 OptionArgVectorSP ret_val;
2211
2212 auto pos = m_alias_dict.find(alias_name);
2213 if (pos != m_alias_dict.end())
2214 return (CommandAlias *)pos->second.get();
2215
2216 return nullptr;
2217}
2218
2219bool CommandInterpreter::HasCommands() const { return (!m_command_dict.empty()); }
2220
2221bool CommandInterpreter::HasAliases() const { return (!m_alias_dict.empty()); }
2222
2223bool CommandInterpreter::HasUserCommands() const { return (!m_user_dict.empty()); }
2224
2226 return (!m_user_mw_dict.empty());
2227}
2228
2230
2232 const char *alias_name,
2233 Args &cmd_args,
2234 std::string &raw_input_string,
2235 CommandReturnObject &result) {
2236 OptionArgVectorSP option_arg_vector_sp =
2237 GetAlias(alias_name)->GetOptionArguments();
2238
2239 bool wants_raw_input = alias_cmd_obj->WantsRawCommandString();
2240
2241 // Make sure that the alias name is the 0th element in cmd_args
2242 std::string alias_name_str = alias_name;
2243 if (alias_name_str != cmd_args.GetArgumentAtIndex(0))
2244 cmd_args.Unshift(alias_name_str);
2245
2246 Args new_args(alias_cmd_obj->GetCommandName());
2247 if (new_args.GetArgumentCount() == 2)
2248 new_args.Shift();
2249
2250 if (option_arg_vector_sp.get()) {
2251 if (wants_raw_input) {
2252 // We have a command that both has command options and takes raw input.
2253 // Make *sure* it has a " -- " in the right place in the
2254 // raw_input_string.
2255 size_t pos = raw_input_string.find(" -- ");
2256 if (pos == std::string::npos) {
2257 // None found; assume it goes at the beginning of the raw input string
2258 raw_input_string.insert(0, " -- ");
2259 }
2260 }
2261
2262 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
2263 const size_t old_size = cmd_args.GetArgumentCount();
2264 std::vector<bool> used(old_size + 1, false);
2265
2266 used[0] = true;
2267
2268 int value_type;
2269 std::string option;
2270 std::string value;
2271 for (const auto &option_entry : *option_arg_vector) {
2272 std::tie(option, value_type, value) = option_entry;
2273 if (option == g_argument) {
2274 if (!wants_raw_input || (value != "--")) {
2275 // Since we inserted this above, make sure we don't insert it twice
2276 new_args.AppendArgument(value);
2277 }
2278 continue;
2279 }
2280
2281 if (value_type != OptionParser::eOptionalArgument)
2282 new_args.AppendArgument(option);
2283
2284 if (value == g_no_argument)
2285 continue;
2286
2287 int index = GetOptionArgumentPosition(value.c_str());
2288 if (index == 0) {
2289 // value was NOT a positional argument; must be a real value
2290 if (value_type != OptionParser::eOptionalArgument)
2291 new_args.AppendArgument(value);
2292 else {
2293 new_args.AppendArgument(option + value);
2294 }
2295
2296 } else if (static_cast<size_t>(index) >= cmd_args.GetArgumentCount()) {
2297 result.AppendErrorWithFormat("Not enough arguments provided; you "
2298 "need at least %d arguments to use "
2299 "this alias.\n",
2300 index);
2301 return;
2302 } else {
2303 // Find and remove cmd_args.GetArgumentAtIndex(i) from raw_input_string
2304 size_t strpos =
2305 raw_input_string.find(cmd_args.GetArgumentAtIndex(index));
2306 if (strpos != std::string::npos) {
2307 raw_input_string = raw_input_string.erase(
2308 strpos, strlen(cmd_args.GetArgumentAtIndex(index)));
2309 }
2310
2311 if (value_type != OptionParser::eOptionalArgument)
2312 new_args.AppendArgument(cmd_args.GetArgumentAtIndex(index));
2313 else {
2314 new_args.AppendArgument(option + cmd_args.GetArgumentAtIndex(index));
2315 }
2316 used[index] = true;
2317 }
2318 }
2319
2320 for (auto entry : llvm::enumerate(cmd_args.entries())) {
2321 if (!used[entry.index()] && !wants_raw_input)
2322 new_args.AppendArgument(entry.value().ref());
2323 }
2324
2325 cmd_args.Clear();
2326 cmd_args.SetArguments(new_args.GetArgumentCount(),
2327 new_args.GetConstArgumentVector());
2328 } else {
2330 // This alias was not created with any options; nothing further needs to be
2331 // done, unless it is a command that wants raw input, in which case we need
2332 // to clear the rest of the data from cmd_args, since its in the raw input
2333 // string.
2334 if (wants_raw_input) {
2335 cmd_args.Clear();
2336 cmd_args.SetArguments(new_args.GetArgumentCount(),
2337 new_args.GetConstArgumentVector());
2338 }
2339 return;
2340 }
2341
2343}
2344
2346 int position = 0; // Any string that isn't an argument position, i.e. '%'
2347 // followed by an integer, gets a position
2348 // of zero.
2349
2350 const char *cptr = in_string;
2351
2352 // Does it start with '%'
2353 if (cptr[0] == '%') {
2354 ++cptr;
2355
2356 // Is the rest of it entirely digits?
2357 if (isdigit(cptr[0])) {
2358 const char *start = cptr;
2359 while (isdigit(cptr[0]))
2360 ++cptr;
2361
2362 // We've gotten to the end of the digits; are we at the end of the
2363 // string?
2364 if (cptr[0] == '\0')
2365 position = atoi(start);
2366 }
2367 }
2368
2369 return position;
2370}
2371
2373 llvm::StringRef suffix = {}) {
2374 std::string init_file_name = ".lldbinit";
2375 if (!suffix.empty()) {
2376 init_file_name.append("-");
2377 init_file_name.append(suffix.str());
2378 }
2379
2381 llvm::sys::path::append(init_file, init_file_name);
2382
2383 FileSystem::Instance().Resolve(init_file);
2384}
2385
2387 LanguageType language) {
2388 if (language == eLanguageTypeUnknown) {
2390 if (auto main_repl_language = repl_languages.GetSingularLanguage())
2391 language = *main_repl_language;
2392 else
2393 return;
2394 }
2395
2396 std::string init_file_name =
2397 (llvm::Twine(".lldbinit-") +
2398 llvm::Twine(Language::GetNameForLanguageType(language)) +
2399 llvm::Twine("-repl"))
2400 .str();
2402 llvm::sys::path::append(init_file, init_file_name);
2403 FileSystem::Instance().Resolve(init_file);
2404}
2405
2407 llvm::StringRef s = ".lldbinit";
2408 init_file.assign(s.begin(), s.end());
2409 FileSystem::Instance().Resolve(init_file);
2410}
2411
2413 CommandReturnObject &result) {
2414 assert(!m_skip_lldbinit_files);
2415
2416 if (!FileSystem::Instance().Exists(file)) {
2418 return;
2419 }
2420
2421 // Use HandleCommand to 'source' the given file; this will do the actual
2422 // broadcasting of the commands back to any appropriate listener (see
2423 // CommandObjectSource::Execute for more details).
2424 const bool saved_batch = SetBatchCommandMode(true);
2426 options.SetSilent(true);
2427 options.SetPrintErrors(true);
2428 options.SetStopOnError(false);
2429 options.SetStopOnContinue(true);
2430 HandleCommandsFromFile(file, options, result);
2431 SetBatchCommandMode(saved_batch);
2432}
2433
2437 return;
2438 }
2439
2440 llvm::SmallString<128> init_file;
2441 GetCwdInitFile(init_file);
2442 if (!FileSystem::Instance().Exists(init_file)) {
2444 return;
2445 }
2446
2447 LoadCWDlldbinitFile should_load =
2449
2450 switch (should_load) {
2453 break;
2455 SourceInitFile(FileSpec(init_file.str()), result);
2456 break;
2457 case eLoadCWDlldbinitWarn: {
2458 llvm::SmallString<128> home_init_file;
2459 GetHomeInitFile(home_init_file);
2460 if (llvm::sys::path::parent_path(init_file) ==
2461 llvm::sys::path::parent_path(home_init_file)) {
2463 } else {
2465 }
2466 }
2467 }
2468}
2469
2470/// We will first see if there is an application specific ".lldbinit" file
2471/// whose name is "~/.lldbinit" followed by a "-" and the name of the program.
2472/// If this file doesn't exist, we fall back to the REPL init file or the
2473/// default home init file in "~/.lldbinit".
2475 bool is_repl) {
2478 return;
2479 }
2480
2481 llvm::SmallString<128> init_file;
2482
2483 if (is_repl)
2484 GetHomeREPLInitFile(init_file, GetDebugger().GetREPLLanguage());
2485
2486 if (init_file.empty())
2487 GetHomeInitFile(init_file);
2488
2489 if (!m_skip_app_init_files) {
2490 llvm::StringRef program_name =
2491 HostInfo::GetProgramFileSpec().GetFilename().GetStringRef();
2492 llvm::SmallString<128> program_init_file;
2493 GetHomeInitFile(program_init_file, program_name);
2494 if (FileSystem::Instance().Exists(program_init_file))
2495 init_file = program_init_file;
2496 }
2497
2498 SourceInitFile(FileSpec(init_file.str()), result);
2499}
2500
2502#ifdef LLDB_GLOBAL_INIT_DIRECTORY
2503 if (!m_skip_lldbinit_files) {
2504 FileSpec init_file(LLDB_GLOBAL_INIT_DIRECTORY);
2505 if (init_file)
2506 init_file.MakeAbsolute(HostInfo::GetShlibDir());
2507
2508 init_file.AppendPathComponent("lldbinit");
2509 SourceInitFile(init_file, result);
2510 return;
2511 }
2512#endif
2514}
2515
2517 const char *prefix = GetDebugger().GetIOHandlerCommandPrefix();
2518 return prefix == nullptr ? "" : prefix;
2519}
2520
2521PlatformSP CommandInterpreter::GetPlatform(bool prefer_target_platform) {
2522 PlatformSP platform_sp;
2523 if (prefer_target_platform) {
2525 Target *target = exe_ctx.GetTargetPtr();
2526 if (target)
2527 platform_sp = target->GetPlatform();
2528 }
2529
2530 if (!platform_sp)
2532 return platform_sp;
2533}
2534
2536 auto exe_ctx = GetExecutionContext();
2537 TargetSP target_sp = exe_ctx.GetTargetSP();
2538 if (!target_sp)
2539 return false;
2540
2541 ProcessSP process_sp(target_sp->GetProcessSP());
2542 if (!process_sp)
2543 return false;
2544
2545 if (eStateStopped != process_sp->GetState())
2546 return false;
2547
2548 for (const auto &thread_sp : process_sp->GetThreadList().Threads()) {
2549 StopInfoSP stop_info = thread_sp->GetStopInfo();
2550 if (!stop_info) {
2551 // If there's no stop_info, keep iterating through the other threads;
2552 // it's enough that any thread has got a stop_info that indicates
2553 // an abnormal stop, to consider the process to be stopped abnormally.
2554 continue;
2555 }
2556
2557 const StopReason reason = stop_info->GetStopReason();
2558 if (reason == eStopReasonException ||
2559 reason == eStopReasonInstrumentation ||
2560 reason == eStopReasonProcessorTrace || reason == eStopReasonInterrupt)
2561 return true;
2562
2563 if (reason == eStopReasonSignal) {
2564 const auto stop_signal = static_cast<int32_t>(stop_info->GetValue());
2565 UnixSignalsSP signals_sp = process_sp->GetUnixSignals();
2566 if (!signals_sp || !signals_sp->SignalIsValid(stop_signal))
2567 // The signal is unknown, treat it as abnormal.
2568 return true;
2569
2570 const auto sigint_num = signals_sp->GetSignalNumberFromName("SIGINT");
2571 const auto sigstop_num = signals_sp->GetSignalNumberFromName("SIGSTOP");
2572 if ((stop_signal != sigint_num) && (stop_signal != sigstop_num))
2573 // The signal very likely implies a crash.
2574 return true;
2575 }
2576 }
2577
2578 return false;
2579}
2580
2581void
2583 const ExecutionContext &override_context,
2584 const CommandInterpreterRunOptions &options,
2585 CommandReturnObject &result) {
2586
2587 OverrideExecutionContext(override_context);
2588 HandleCommands(commands, options, result);
2590}
2591
2593 const CommandInterpreterRunOptions &options,
2594 CommandReturnObject &result) {
2595 size_t num_lines = commands.GetSize();
2596
2597 // If we are going to continue past a "continue" then we need to run the
2598 // commands synchronously. Make sure you reset this value anywhere you return
2599 // from the function.
2600
2601 bool old_async_execution = m_debugger.GetAsyncExecution();
2602
2603 if (!options.GetStopOnContinue()) {
2605 }
2606
2607 for (size_t idx = 0; idx < num_lines; idx++) {
2608 const char *cmd = commands.GetStringAtIndex(idx);
2609 if (cmd[0] == '\0')
2610 continue;
2611
2612 if (options.GetEchoCommands()) {
2613 // TODO: Add Stream support.
2614 result.AppendMessageWithFormat("%s %s\n",
2615 m_debugger.GetPrompt().str().c_str(), cmd);
2616 }
2617
2619 tmp_result.SetInteractive(result.GetInteractive());
2620 tmp_result.SetSuppressImmediateOutput(true);
2621
2622 // We might call into a regex or alias command, in which case the
2623 // add_to_history will get lost. This m_command_source_depth dingus is the
2624 // way we turn off adding to the history in that case, so set it up here.
2625 if (!options.GetAddToHistory())
2627 bool success = HandleCommand(cmd, options.m_add_to_history, tmp_result);
2628 if (!options.GetAddToHistory())
2630
2631 if (options.GetPrintResults()) {
2632 if (tmp_result.Succeeded())
2633 result.AppendMessage(tmp_result.GetOutputString());
2634 }
2635
2636 if (!success || !tmp_result.Succeeded()) {
2637 std::string error_msg = tmp_result.GetErrorString();
2638 if (error_msg.empty())
2639 error_msg = "<unknown error>.\n";
2640 if (options.GetStopOnError()) {
2641 result.AppendErrorWithFormatv("Aborting reading of commands after "
2642 "command #{0}: '{1}' failed with {2}",
2643 (uint64_t)idx, cmd, error_msg);
2644 m_debugger.SetAsyncExecution(old_async_execution);
2645 return;
2646 } else if (options.GetPrintResults()) {
2647 result.AppendMessageWithFormatv("Command #{0} '{1}' failed with {2}",
2648 (uint64_t)idx + 1, cmd, error_msg);
2649 }
2650 }
2651
2652 if (result.GetImmediateOutputStream())
2653 result.GetImmediateOutputStream()->Flush();
2654
2655 if (result.GetImmediateErrorStream())
2656 result.GetImmediateErrorStream()->Flush();
2657
2658 // N.B. Can't depend on DidChangeProcessState, because the state coming
2659 // into the command execution could be running (for instance in Breakpoint
2660 // Commands. So we check the return value to see if it is has running in
2661 // it.
2662 if ((tmp_result.GetStatus() == eReturnStatusSuccessContinuingNoResult) ||
2664 if (options.GetStopOnContinue()) {
2665 // If we caused the target to proceed, and we're going to stop in that
2666 // case, set the status in our real result before returning. This is
2667 // an error if the continue was not the last command in the set of
2668 // commands to be run.
2669 if (idx != num_lines - 1)
2670 result.AppendErrorWithFormat(
2671 "Aborting reading of commands after command #%" PRIu64
2672 ": '%s' continued the target.\n",
2673 (uint64_t)idx + 1, cmd);
2674 else
2675 result.AppendMessageWithFormat("Command #%" PRIu64
2676 " '%s' continued the target.\n",
2677 (uint64_t)idx + 1, cmd);
2678
2679 result.SetStatus(tmp_result.GetStatus());
2680 m_debugger.SetAsyncExecution(old_async_execution);
2681
2682 return;
2683 }
2684 }
2685
2686 // Also check for "stop on crash here:
2687 if (tmp_result.GetDidChangeProcessState() && options.GetStopOnCrash() &&
2689 if (idx != num_lines - 1)
2690 result.AppendErrorWithFormat(
2691 "Aborting reading of commands after command #%" PRIu64
2692 ": '%s' stopped with a signal or exception.\n",
2693 (uint64_t)idx + 1, cmd);
2694 else
2696 "Command #%" PRIu64 " '%s' stopped with a signal or exception.\n",
2697 (uint64_t)idx + 1, cmd);
2698
2699 result.SetStatus(tmp_result.GetStatus());
2700 m_debugger.SetAsyncExecution(old_async_execution);
2701
2702 return;
2703 }
2704 }
2705
2707 m_debugger.SetAsyncExecution(old_async_execution);
2708}
2709
2710// Make flags that we can pass into the IOHandler so our delegates can do the
2711// right thing
2712enum {
2722
2724 FileSpec &cmd_file, const ExecutionContext &context,
2725 const CommandInterpreterRunOptions &options, CommandReturnObject &result) {
2726 OverrideExecutionContext(context);
2727 HandleCommandsFromFile(cmd_file, options, result);
2729}
2730
2732 const CommandInterpreterRunOptions &options, CommandReturnObject &result) {
2733 if (!FileSystem::Instance().Exists(cmd_file)) {
2734 result.AppendErrorWithFormat(
2735 "Error reading commands from file %s - file not found.\n",
2736 cmd_file.GetFilename().AsCString("<Unknown>"));
2737 return;
2738 }
2739
2740 std::string cmd_file_path = cmd_file.GetPath();
2741 auto input_file_up =
2743 if (!input_file_up) {
2744 std::string error = llvm::toString(input_file_up.takeError());
2746 "error: an error occurred read file '{0}': {1}\n", cmd_file_path,
2747 llvm::fmt_consume(input_file_up.takeError()));
2748 return;
2749 }
2750 FileSP input_file_sp = FileSP(std::move(input_file_up.get()));
2751
2752 Debugger &debugger = GetDebugger();
2753
2754 uint32_t flags = 0;
2755
2756 if (options.m_stop_on_continue == eLazyBoolCalculate) {
2757 if (m_command_source_flags.empty()) {
2758 // Stop on continue by default
2760 } else if (m_command_source_flags.back() &
2763 }
2764 } else if (options.m_stop_on_continue == eLazyBoolYes) {
2766 }
2767
2768 if (options.m_stop_on_error == eLazyBoolCalculate) {
2769 if (m_command_source_flags.empty()) {
2774 }
2775 } else if (options.m_stop_on_error == eLazyBoolYes) {
2777 }
2778
2779 // stop-on-crash can only be set, if it is present in all levels of
2780 // pushed flag sets.
2781 if (options.GetStopOnCrash()) {
2782 if (m_command_source_flags.empty()) {
2786 }
2787 }
2788
2789 if (options.m_echo_commands == eLazyBoolCalculate) {
2790 if (m_command_source_flags.empty()) {
2791 // Echo command by default
2795 }
2796 } else if (options.m_echo_commands == eLazyBoolYes) {
2798 }
2799
2800 // We will only ever ask for this flag, if we echo commands in general.
2802 if (m_command_source_flags.empty()) {
2803 // Echo comments by default
2805 } else if (m_command_source_flags.back() &
2808 }
2809 } else if (options.m_echo_comment_commands == eLazyBoolYes) {
2811 }
2812
2813 if (options.m_print_results == eLazyBoolCalculate) {
2814 if (m_command_source_flags.empty()) {
2815 // Print output by default
2819 }
2820 } else if (options.m_print_results == eLazyBoolYes) {
2822 }
2823
2824 if (options.m_print_errors == eLazyBoolCalculate) {
2825 if (m_command_source_flags.empty()) {
2826 // Print output by default
2830 }
2831 } else if (options.m_print_errors == eLazyBoolYes) {
2833 }
2834
2835 if (flags & eHandleCommandFlagPrintResult) {
2836 debugger.GetOutputFile().Printf("Executing commands in '%s'.\n",
2837 cmd_file_path.c_str());
2838 }
2839
2840 // Used for inheriting the right settings when "command source" might
2841 // have nested "command source" commands
2842 lldb::StreamFileSP empty_stream_sp;
2843 m_command_source_flags.push_back(flags);
2844 IOHandlerSP io_handler_sp(new IOHandlerEditline(
2845 debugger, IOHandler::Type::CommandInterpreter, input_file_sp,
2846 empty_stream_sp, // Pass in an empty stream so we inherit the top
2847 // input reader output stream
2848 empty_stream_sp, // Pass in an empty stream so we inherit the top
2849 // input reader error stream
2850 flags,
2851 nullptr, // Pass in NULL for "editline_name" so no history is saved,
2852 // or written
2853 debugger.GetPrompt(), llvm::StringRef(),
2854 false, // Not multi-line
2855 debugger.GetUseColor(), 0, *this));
2856 const bool old_async_execution = debugger.GetAsyncExecution();
2857
2858 // Set synchronous execution if we are not stopping on continue
2859 if ((flags & eHandleCommandFlagStopOnContinue) == 0)
2860 debugger.SetAsyncExecution(false);
2861
2864
2865 debugger.RunIOHandlerSync(io_handler_sp);
2866 if (!m_command_source_flags.empty())
2867 m_command_source_flags.pop_back();
2868
2869 m_command_source_dirs.pop_back();
2871
2873 debugger.SetAsyncExecution(old_async_execution);
2874}
2875
2877
2880}
2881
2883 llvm::StringRef prefix,
2884 llvm::StringRef help_text) {
2885 const uint32_t max_columns = m_debugger.GetTerminalWidth();
2886
2887 size_t line_width_max = max_columns - prefix.size();
2888 if (line_width_max < 16)
2889 line_width_max = help_text.size() + prefix.size();
2890
2891 strm.IndentMore(prefix.size());
2892 bool prefixed_yet = false;
2893 // Even if we have no help text we still want to emit the command name.
2894 if (help_text.empty())
2895 help_text = "No help text";
2896 while (!help_text.empty()) {
2897 // Prefix the first line, indent subsequent lines to line up
2898 if (!prefixed_yet) {
2899 strm << prefix;
2900 prefixed_yet = true;
2901 } else
2902 strm.Indent();
2903
2904 // Never print more than the maximum on one line.
2905 llvm::StringRef this_line = help_text.substr(0, line_width_max);
2906
2907 // Always break on an explicit newline.
2908 std::size_t first_newline = this_line.find_first_of("\n");
2909
2910 // Don't break on space/tab unless the text is too long to fit on one line.
2911 std::size_t last_space = llvm::StringRef::npos;
2912 if (this_line.size() != help_text.size())
2913 last_space = this_line.find_last_of(" \t");
2914
2915 // Break at whichever condition triggered first.
2916 this_line = this_line.substr(0, std::min(first_newline, last_space));
2917 strm.PutCString(this_line);
2918 strm.EOL();
2919
2920 // Remove whitespace / newlines after breaking.
2921 help_text = help_text.drop_front(this_line.size()).ltrim();
2922 }
2923 strm.IndentLess(prefix.size());
2924}
2925
2927 llvm::StringRef word_text,
2928 llvm::StringRef separator,
2929 llvm::StringRef help_text,
2930 size_t max_word_len) {
2931 StreamString prefix_stream;
2932 prefix_stream.Printf(" %-*s %*s ", (int)max_word_len, word_text.data(),
2933 (int)separator.size(), separator.data());
2934 OutputFormattedHelpText(strm, prefix_stream.GetString(), help_text);
2935}
2936
2937void CommandInterpreter::OutputHelpText(Stream &strm, llvm::StringRef word_text,
2938 llvm::StringRef separator,
2939 llvm::StringRef help_text,
2940 uint32_t max_word_len) {
2941 int indent_size = max_word_len + separator.size() + 2;
2942
2943 strm.IndentMore(indent_size);
2944
2945 StreamString text_strm;
2946 text_strm.Printf("%-*s ", (int)max_word_len, word_text.data());
2947 text_strm << separator << " " << help_text;
2948
2949 const uint32_t max_columns = m_debugger.GetTerminalWidth();
2950
2951 llvm::StringRef text = text_strm.GetString();
2952
2953 uint32_t chars_left = max_columns;
2954
2955 auto nextWordLength = [](llvm::StringRef S) {
2956 size_t pos = S.find(' ');
2957 return pos == llvm::StringRef::npos ? S.size() : pos;
2958 };
2959
2960 while (!text.empty()) {
2961 if (text.front() == '\n' ||
2962 (text.front() == ' ' && nextWordLength(text.ltrim(' ')) > chars_left)) {
2963 strm.EOL();
2964 strm.Indent();
2965 chars_left = max_columns - indent_size;
2966 if (text.front() == '\n')
2967 text = text.drop_front();
2968 else
2969 text = text.ltrim(' ');
2970 } else {
2971 strm.PutChar(text.front());
2972 --chars_left;
2973 text = text.drop_front();
2974 }
2975 }
2976
2977 strm.EOL();
2978 strm.IndentLess(indent_size);
2979}
2980
2982 llvm::StringRef search_word, StringList &commands_found,
2983 StringList &commands_help, const CommandObject::CommandMap &command_map) {
2984 for (const auto &pair : command_map) {
2985 llvm::StringRef command_name = pair.first;
2986 CommandObject *cmd_obj = pair.second.get();
2987
2988 const bool search_short_help = true;
2989 const bool search_long_help = false;
2990 const bool search_syntax = false;
2991 const bool search_options = false;
2992 if (command_name.contains_insensitive(search_word) ||
2993 cmd_obj->HelpTextContainsWord(search_word, search_short_help,
2994 search_long_help, search_syntax,
2995 search_options)) {
2996 commands_found.AppendString(command_name);
2997 commands_help.AppendString(cmd_obj->GetHelp());
2998 }
2999
3000 if (auto *multiword_cmd = cmd_obj->GetAsMultiwordCommand()) {
3001 StringList subcommands_found;
3002 FindCommandsForApropos(search_word, subcommands_found, commands_help,
3003 multiword_cmd->GetSubcommandDictionary());
3004 for (const auto &subcommand_name : subcommands_found) {
3005 std::string qualified_name =
3006 (command_name + " " + subcommand_name).str();
3007 commands_found.AppendString(qualified_name);
3008 }
3009 }
3010 }
3011}
3012
3013void CommandInterpreter::FindCommandsForApropos(llvm::StringRef search_word,
3014 StringList &commands_found,
3015 StringList &commands_help,
3016 bool search_builtin_commands,
3017 bool search_user_commands,
3018 bool search_alias_commands,
3019 bool search_user_mw_commands) {
3020 CommandObject::CommandMap::const_iterator pos;
3021
3022 if (search_builtin_commands)
3023 FindCommandsForApropos(search_word, commands_found, commands_help,
3025
3026 if (search_user_commands)
3027 FindCommandsForApropos(search_word, commands_found, commands_help,
3028 m_user_dict);
3029
3030 if (search_user_mw_commands)
3031 FindCommandsForApropos(search_word, commands_found, commands_help,
3033
3034 if (search_alias_commands)
3035 FindCommandsForApropos(search_word, commands_found, commands_help,
3036 m_alias_dict);
3037}
3038
3040 return !m_overriden_exe_contexts.empty()
3043}
3044
3046 const ExecutionContext &override_context) {
3047 m_overriden_exe_contexts.push(override_context);
3048}
3049
3051 if (!m_overriden_exe_contexts.empty())
3053}
3054
3056 if (ProcessSP process_sp = GetExecutionContext().GetProcessSP())
3057 m_debugger.FlushProcessOutput(*process_sp, /*flush_stdout*/ true,
3058 /*flush_stderr*/ true);
3059}
3060
3062 auto idle_state = CommandHandlingState::eIdle;
3063 if (m_command_state.compare_exchange_strong(
3066 else
3069}
3070
3073 if (--m_iohandler_nesting_level == 0) {
3074 auto prev_state = m_command_state.exchange(CommandHandlingState::eIdle);
3076 }
3077}
3078
3080 auto in_progress = CommandHandlingState::eInProgress;
3081 return m_command_state.compare_exchange_strong(
3083}
3084
3087 return false;
3088
3089 bool was_interrupted =
3091 lldbassert(!was_interrupted || m_iohandler_nesting_level > 0);
3092 return was_interrupted;
3093}
3094
3096 llvm::StringRef str,
3097 bool is_stdout) {
3098
3099 lldb::StreamFileSP stream = is_stdout ? io_handler.GetOutputStreamFileSP()
3100 : io_handler.GetErrorStreamFileSP();
3101 // Split the output into lines and poll for interrupt requests
3102 bool had_output = !str.empty();
3103 while (!str.empty()) {
3104 llvm::StringRef line;
3105 std::tie(line, str) = str.split('\n');
3106 {
3107 std::lock_guard<std::recursive_mutex> guard(io_handler.GetOutputMutex());
3108 stream->Write(line.data(), line.size());
3109 stream->Write("\n", 1);
3110 }
3111 }
3112
3113 std::lock_guard<std::recursive_mutex> guard(io_handler.GetOutputMutex());
3114 if (had_output &&
3115 INTERRUPT_REQUESTED(GetDebugger(), "Interrupted dumping command output"))
3116 stream->Printf("\n... Interrupted.\n");
3117 stream->Flush();
3118}
3119
3121 llvm::StringRef line, const Flags &io_handler_flags) const {
3122 if (!io_handler_flags.Test(eHandleCommandFlagEchoCommand))
3123 return false;
3124
3125 llvm::StringRef command = line.trim();
3126 if (command.empty())
3127 return true;
3128
3129 if (command.front() == m_comment_char)
3130 return io_handler_flags.Test(eHandleCommandFlagEchoCommentCommand);
3131
3132 return true;
3133}
3134
3136 std::string &line) {
3137 // If we were interrupted, bail out...
3138 if (WasInterrupted())
3139 return;
3140
3141 const bool is_interactive = io_handler.GetIsInteractive();
3142 const bool allow_repeats =
3144
3145 if (!is_interactive && !allow_repeats) {
3146 // When we are not interactive, don't execute blank lines. This will happen
3147 // sourcing a commands file. We don't want blank lines to repeat the
3148 // previous command and cause any errors to occur (like redefining an
3149 // alias, get an error and stop parsing the commands file).
3150 // But obey the AllowRepeats flag if the user has set it.
3151 if (line.empty())
3152 return;
3153 }
3154 if (!is_interactive) {
3155 // When using a non-interactive file handle (like when sourcing commands
3156 // from a file) we need to echo the command out so we don't just see the
3157 // command output and no command...
3158 if (EchoCommandNonInteractive(line, io_handler.GetFlags())) {
3159 std::lock_guard<std::recursive_mutex> guard(io_handler.GetOutputMutex());
3160 io_handler.GetOutputStreamFileSP()->Printf(
3161 "%s%s\n", io_handler.GetPrompt(), line.c_str());
3162 }
3163 }
3164
3166
3168 bool pushed_exe_ctx = false;
3169 if (exe_ctx.HasTargetScope()) {
3170 OverrideExecutionContext(exe_ctx);
3171 pushed_exe_ctx = true;
3172 }
3173 auto finalize = llvm::make_scope_exit([this, pushed_exe_ctx]() {
3174 if (pushed_exe_ctx)
3176 });
3177
3179 HandleCommand(line.c_str(), eLazyBoolCalculate, result);
3180
3181 // Now emit the command output text from the command we just executed
3182 if ((result.Succeeded() &&
3185 // Display any inline diagnostics first.
3186 const bool inline_diagnostics = !result.GetImmediateErrorStream() &&
3188 if (inline_diagnostics) {
3189 unsigned prompt_len = m_debugger.GetPrompt().size();
3190 if (auto indent = result.GetDiagnosticIndent()) {
3191 std::string diags =
3192 result.GetInlineDiagnosticString(prompt_len + *indent);
3193 PrintCommandOutput(io_handler, diags, true);
3194 }
3195 }
3196
3197 // Display any STDOUT/STDERR _prior_ to emitting the command result text.
3199
3200 if (!result.GetImmediateOutputStream()) {
3201 llvm::StringRef output = result.GetOutputString();
3202 PrintCommandOutput(io_handler, output, true);
3203 }
3204
3205 // Now emit the command error text from the command we just executed.
3206 if (!result.GetImmediateErrorStream()) {
3207 std::string error = result.GetErrorString(!inline_diagnostics);
3208 PrintCommandOutput(io_handler, error, false);
3209 }
3210 }
3211
3213
3214 switch (result.GetStatus()) {
3219 break;
3220
3224 io_handler.SetIsDone(true);
3225 break;
3226
3229 if (io_handler.GetFlags().Test(eHandleCommandFlagStopOnError)) {
3231 io_handler.SetIsDone(true);
3232 }
3233 break;
3234
3235 case eReturnStatusQuit:
3237 io_handler.SetIsDone(true);
3238 break;
3239 }
3240
3241 // Finally, if we're going to stop on crash, check that here:
3243 result.GetDidChangeProcessState() &&
3246 io_handler.SetIsDone(true);
3248 }
3249}
3250
3253 Process *process = exe_ctx.GetProcessPtr();
3254
3255 if (InterruptCommand())
3256 return true;
3257
3258 if (process) {
3259 StateType state = process->GetState();
3260 if (StateIsRunningState(state)) {
3261 process->Halt();
3262 return true; // Don't do any updating when we are running
3263 }
3264 }
3265
3266 ScriptInterpreter *script_interpreter =
3268 if (script_interpreter) {
3269 if (script_interpreter->Interrupt())
3270 return true;
3271 }
3272 return false;
3273}
3274
3276 CommandReturnObject &result, std::optional<std::string> output_file) {
3277 if (output_file == std::nullopt || output_file->empty()) {
3278 std::string now = llvm::to_string(std::chrono::system_clock::now());
3279 std::replace(now.begin(), now.end(), ' ', '_');
3280 // Can't have file name with colons on Windows
3281 std::replace(now.begin(), now.end(), ':', '-');
3282 const std::string file_name = "lldb_session_" + now + ".log";
3283
3284 FileSpec save_location = GetSaveSessionDirectory();
3285
3286 if (!save_location)
3287 save_location = HostInfo::GetGlobalTempDir();
3288
3289 FileSystem::Instance().Resolve(save_location);
3290 save_location.AppendPathComponent(file_name);
3291 output_file = save_location.GetPath();
3292 }
3293
3294 auto error_out = [&](llvm::StringRef error_message, std::string description) {
3295 LLDB_LOG(GetLog(LLDBLog::Commands), "{0} ({1}:{2})", error_message,
3296 output_file, description);
3298 "Failed to save session's transcripts to {0}!", *output_file);
3299 return false;
3300 };
3301
3305
3306 auto opened_file = FileSystem::Instance().Open(FileSpec(*output_file), flags);
3307
3308 if (!opened_file)
3309 return error_out("Unable to create file",
3310 llvm::toString(opened_file.takeError()));
3311
3312 FileUP file = std::move(opened_file.get());
3313
3314 size_t byte_size = m_transcript_stream.GetSize();
3315
3316 Status error = file->Write(m_transcript_stream.GetData(), byte_size);
3317
3318 if (error.Fail() || byte_size != m_transcript_stream.GetSize())
3319 return error_out("Unable to write to destination file",
3320 "Bytes written do not match transcript size.");
3321
3323 result.AppendMessageWithFormat("Session's transcripts saved to %s\n",
3324 output_file->c_str());
3325 if (!GetSaveTranscript())
3326 result.AppendError(
3327 "Note: the setting interpreter.save-transcript is set to false, so the "
3328 "transcript might not have been recorded.");
3329
3331 const FileSpec file_spec;
3332 error = file->GetFileSpec(const_cast<FileSpec &>(file_spec));
3333 if (error.Success()) {
3334 if (llvm::Error e = Host::OpenFileInExternalEditor(
3335 m_debugger.GetExternalEditor(), file_spec, 1))
3336 result.AppendError(llvm::toString(std::move(e)));
3337 }
3338 }
3339
3340 return true;
3341}
3342
3344 return (GetIOHandler() ? GetIOHandler()->GetIsInteractive() : false);
3345}
3346
3348 if (m_command_source_dirs.empty())
3349 return {};
3350 return m_command_source_dirs.back();
3351}
3352
3354 const char *prompt, IOHandlerDelegate &delegate, void *baton) {
3355 Debugger &debugger = GetDebugger();
3356 IOHandlerSP io_handler_sp(
3358 "lldb", // Name of input reader for history
3359 llvm::StringRef(prompt), // Prompt
3360 llvm::StringRef(), // Continuation prompt
3361 true, // Get multiple lines
3362 debugger.GetUseColor(),
3363 0, // Don't show line numbers
3364 delegate)); // IOHandlerDelegate
3365
3366 if (io_handler_sp) {
3367 io_handler_sp->SetUserData(baton);
3368 debugger.RunIOHandlerAsync(io_handler_sp);
3369 }
3370}
3371
3373 const char *prompt, IOHandlerDelegate &delegate, void *baton) {
3374 Debugger &debugger = GetDebugger();
3375 IOHandlerSP io_handler_sp(
3377 "lldb-python", // Name of input reader for history
3378 llvm::StringRef(prompt), // Prompt
3379 llvm::StringRef(), // Continuation prompt
3380 true, // Get multiple lines
3381 debugger.GetUseColor(),
3382 0, // Don't show line numbers
3383 delegate)); // IOHandlerDelegate
3384
3385 if (io_handler_sp) {
3386 io_handler_sp->SetUserData(baton);
3387 debugger.RunIOHandlerAsync(io_handler_sp);
3388 }
3389}
3390
3393}
3394
3398 // Always re-create the IOHandlerEditline in case the input changed. The old
3399 // instance might have had a non-interactive input and now it does or vice
3400 // versa.
3401 if (force_create || !m_command_io_handler_sp) {
3402 // Always re-create the IOHandlerEditline in case the input changed. The
3403 // old instance might have had a non-interactive input and now it does or
3404 // vice versa.
3405 uint32_t flags = 0;
3406
3407 if (options) {
3408 if (options->m_stop_on_continue == eLazyBoolYes)
3410 if (options->m_stop_on_error == eLazyBoolYes)
3412 if (options->m_stop_on_crash == eLazyBoolYes)
3414 if (options->m_echo_commands != eLazyBoolNo)
3416 if (options->m_echo_comment_commands != eLazyBoolNo)
3418 if (options->m_print_results != eLazyBoolNo)
3420 if (options->m_print_errors != eLazyBoolNo)
3422 if (options->m_allow_repeats == eLazyBoolYes)
3424 } else {
3427 }
3428
3429 m_command_io_handler_sp = std::make_shared<IOHandlerEditline>(
3432 m_debugger.GetErrorStreamSP(), flags, "lldb", m_debugger.GetPrompt(),
3433 llvm::StringRef(), // Continuation prompt
3434 false, // Don't enable multiple line input, just single line commands
3436 0, // Don't show line numbers
3437 *this); // IOHandlerDelegate
3438 }
3440}
3441
3444 // Always re-create the command interpreter when we run it in case any file
3445 // handles have changed.
3446 bool force_create = true;
3447 m_debugger.RunIOHandlerAsync(GetIOHandler(force_create, &options));
3449
3450 if (options.GetAutoHandleEvents())
3452
3453 if (options.GetSpawnThread()) {
3455 } else {
3456 // If the current thread is not managed by a host thread, we won't detect
3457 // that this IS the CommandInterpreter IOHandler thread, so make it so:
3458 HostThread new_io_handler_thread(Host::GetCurrentThread());
3459 HostThread old_io_handler_thread =
3460 m_debugger.SetIOHandlerThread(new_io_handler_thread);
3462 m_debugger.SetIOHandlerThread(old_io_handler_thread);
3463
3464 if (options.GetAutoHandleEvents())
3466 }
3467
3468 return m_result;
3469}
3470
3473 CommandReturnObject &result) {
3474 std::string scratch_command(command_line); // working copy so we don't modify
3475 // command_line unless we succeed
3476 CommandObject *cmd_obj = nullptr;
3477 StreamString revised_command_line;
3478 bool wants_raw_input = false;
3479 std::string next_word;
3480 StringList matches;
3481 bool done = false;
3482
3483 auto build_alias_cmd = [&](std::string &full_name) {
3484 revised_command_line.Clear();
3485 matches.Clear();
3486 std::string alias_result;
3487 cmd_obj =
3488 BuildAliasResult(full_name, scratch_command, alias_result, result);
3489 revised_command_line.Printf("%s", alias_result.c_str());
3490 if (cmd_obj) {
3491 wants_raw_input = cmd_obj->WantsRawCommandString();
3492 }
3493 };
3494
3495 while (!done) {
3496 char quote_char = '\0';
3497 std::string suffix;
3498 ExtractCommand(scratch_command, next_word, suffix, quote_char);
3499 if (cmd_obj == nullptr) {
3500 std::string full_name;
3501 bool is_alias = GetAliasFullName(next_word, full_name);
3502 cmd_obj = GetCommandObject(next_word, &matches);
3503 bool is_real_command =
3504 (!is_alias) || (cmd_obj != nullptr && !cmd_obj->IsAlias());
3505 if (!is_real_command) {
3506 build_alias_cmd(full_name);
3507 } else {
3508 if (cmd_obj) {
3509 llvm::StringRef cmd_name = cmd_obj->GetCommandName();
3510 revised_command_line.Printf("%s", cmd_name.str().c_str());
3511 wants_raw_input = cmd_obj->WantsRawCommandString();
3512 } else {
3513 revised_command_line.Printf("%s", next_word.c_str());
3514 }
3515 }
3516 } else {
3517 if (cmd_obj->IsMultiwordObject()) {
3518 CommandObject *sub_cmd_obj =
3519 cmd_obj->GetSubcommandObject(next_word.c_str());
3520 if (sub_cmd_obj) {
3521 // The subcommand's name includes the parent command's name, so
3522 // restart rather than append to the revised_command_line.
3523 llvm::StringRef sub_cmd_name = sub_cmd_obj->GetCommandName();
3524 revised_command_line.Clear();
3525 revised_command_line.Printf("%s", sub_cmd_name.str().c_str());
3526 cmd_obj = sub_cmd_obj;
3527 wants_raw_input = cmd_obj->WantsRawCommandString();
3528 } else {
3529 if (quote_char)
3530 revised_command_line.Printf(" %c%s%s%c", quote_char,
3531 next_word.c_str(), suffix.c_str(),
3532 quote_char);
3533 else
3534 revised_command_line.Printf(" %s%s", next_word.c_str(),
3535 suffix.c_str());
3536 done = true;
3537 }
3538 } else {
3539 if (quote_char)
3540 revised_command_line.Printf(" %c%s%s%c", quote_char,
3541 next_word.c_str(), suffix.c_str(),
3542 quote_char);
3543 else
3544 revised_command_line.Printf(" %s%s", next_word.c_str(),
3545 suffix.c_str());
3546 done = true;
3547 }
3548 }
3549
3550 if (cmd_obj == nullptr) {
3551 const size_t num_matches = matches.GetSize();
3552 if (matches.GetSize() > 1) {
3553 StringList alias_matches;
3554 GetAliasCommandObject(next_word, &alias_matches);
3555
3556 if (alias_matches.GetSize() == 1) {
3557 std::string full_name;
3558 GetAliasFullName(alias_matches.GetStringAtIndex(0), full_name);
3559 build_alias_cmd(full_name);
3560 done = static_cast<bool>(cmd_obj);
3561 } else {
3562 StreamString error_msg;
3563 error_msg.Printf("Ambiguous command '%s'. Possible matches:\n",
3564 next_word.c_str());
3565
3566 for (uint32_t i = 0; i < num_matches; ++i) {
3567 error_msg.Printf("\t%s\n", matches.GetStringAtIndex(i));
3568 }
3569 result.AppendRawError(error_msg.GetString());
3570 }
3571 } else {
3572 // We didn't have only one match, otherwise we wouldn't get here.
3573 lldbassert(num_matches == 0);
3574 result.AppendErrorWithFormat("'%s' is not a valid command.\n",
3575 next_word.c_str());
3576 }
3577 if (!done)
3578 return nullptr;
3579 }
3580
3581 if (cmd_obj->IsMultiwordObject()) {
3582 if (!suffix.empty()) {
3583 result.AppendErrorWithFormat(
3584 "command '%s' did not recognize '%s%s%s' as valid (subcommand "
3585 "might be invalid).\n",
3586 cmd_obj->GetCommandName().str().c_str(),
3587 next_word.empty() ? "" : next_word.c_str(),
3588 next_word.empty() ? " -- " : " ", suffix.c_str());
3589 return nullptr;
3590 }
3591 } else {
3592 // If we found a normal command, we are done
3593 done = true;
3594 if (!suffix.empty()) {
3595 switch (suffix[0]) {
3596 case '/':
3597 // GDB format suffixes
3598 {
3599 Options *command_options = cmd_obj->GetOptions();
3600 if (command_options &&
3601 command_options->SupportsLongOption("gdb-format")) {
3602 std::string gdb_format_option("--gdb-format=");
3603 gdb_format_option += (suffix.c_str() + 1);
3604
3605 std::string cmd = std::string(revised_command_line.GetString());
3606 size_t arg_terminator_idx = FindArgumentTerminator(cmd);
3607 if (arg_terminator_idx != std::string::npos) {
3608 // Insert the gdb format option before the "--" that terminates
3609 // options
3610 gdb_format_option.append(1, ' ');
3611 cmd.insert(arg_terminator_idx, gdb_format_option);
3612 revised_command_line.Clear();
3613 revised_command_line.PutCString(cmd);
3614 } else
3615 revised_command_line.Printf(" %s", gdb_format_option.c_str());
3616
3617 if (wants_raw_input &&
3618 FindArgumentTerminator(cmd) == std::string::npos)
3619 revised_command_line.PutCString(" --");
3620 } else {
3621 result.AppendErrorWithFormat(
3622 "the '%s' command doesn't support the --gdb-format option\n",
3623 cmd_obj->GetCommandName().str().c_str());
3624 return nullptr;
3625 }
3626 }
3627 break;
3628
3629 default:
3630 result.AppendErrorWithFormat(
3631 "unknown command shorthand suffix: '%s'\n", suffix.c_str());
3632 return nullptr;
3633 }
3634 }
3635 }
3636 if (scratch_command.empty())
3637 done = true;
3638 }
3639
3640 if (!scratch_command.empty())
3641 revised_command_line.Printf(" %s", scratch_command.c_str());
3642
3643 if (cmd_obj != nullptr)
3644 command_line = std::string(revised_command_line.GetString());
3645
3646 return cmd_obj;
3647}
3648
3650 llvm::json::Object stats;
3651 for (const auto &command_usage : m_command_usages)
3652 stats.try_emplace(command_usage.getKey(), command_usage.getValue());
3653 return stats;
3654}
3655
3657 return m_transcript;
3658}
static const char * k_valid_command_chars
static constexpr const char * InitFileWarning
static size_t FindArgumentTerminator(const std::string &s)
#define REGISTER_COMMAND_OBJECT(NAME, CLASS)
static void StripLeadingSpaces(std::string &s)
static void GetHomeREPLInitFile(llvm::SmallVectorImpl< char > &init_file, LanguageType language)
static void GetCwdInitFile(llvm::SmallVectorImpl< char > &init_file)
static const char * k_white_space
static void GetHomeInitFile(llvm::SmallVectorImpl< char > &init_file, llvm::StringRef suffix={})
@ eHandleCommandFlagAllowRepeats
@ eHandleCommandFlagStopOnCrash
@ eHandleCommandFlagEchoCommentCommand
@ eHandleCommandFlagStopOnError
@ eHandleCommandFlagStopOnContinue
@ eHandleCommandFlagPrintErrors
@ eHandleCommandFlagEchoCommand
@ eHandleCommandFlagPrintResult
static bool ExtractCommand(std::string &command_string, std::string &command, std::string &suffix, char &quote_char)
static llvm::raw_ostream & error(Stream &strm)
#define INTERRUPT_REQUESTED(debugger,...)
This handy define will keep you from having to generate a report for the interruption by hand.
Definition: Debugger.h:454
#define lldbassert(x)
Definition: LLDBAssert.h:15
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition: Log.h:369
#define LLDB_LOGF(log,...)
Definition: Log.h:376
static double elapsed(const StatsTimepoint &start, const StatsTimepoint &end)
Definition: Statistics.cpp:39
#define LLDB_SCOPED_TIMER()
Definition: Timer.h:83
#define LLDB_SCOPED_TIMERF(...)
Definition: Timer.h:86
A command line argument class.
Definition: Args.h:33
void Unshift(llvm::StringRef arg_str, char quote_char='\0')
Inserts a class owned copy of arg_str at the beginning of the argument vector.
Definition: Args.cpp:303
void Shift()
Shifts the first argument C string value of the array off the argument array.
Definition: Args.cpp:295
void SetArguments(size_t argc, const char **argv)
Sets the argument vector value, optionally copying all arguments into an internal buffer.
Definition: Args.cpp:367
size_t GetArgumentCount() const
Gets the number of arguments left in this command object.
Definition: Args.h:120
void AppendArgument(llvm::StringRef arg_str, char quote_char='\0')
Appends a new argument to the end of the list argument list.
Definition: Args.cpp:332
llvm::ArrayRef< ArgEntry > entries() const
Definition: Args.h:132
const char * GetArgumentAtIndex(size_t idx) const
Gets the NULL terminated C string argument pointer for the argument at index idx.
Definition: Args.cpp:273
const char ** GetConstArgumentVector() const
Gets the argument vector.
Definition: Args.cpp:289
void Clear()
Clear the arguments.
Definition: Args.cpp:388
An event broadcasting class.
Definition: Broadcaster.h:146
void SetEventName(uint32_t event_mask, const char *name)
Set the name for an event bit.
Definition: Broadcaster.h:243
void BroadcastEvent(lldb::EventSP &event_sp)
Broadcast an event which has no associated data.
Definition: Broadcaster.h:168
OptionArgVectorSP GetOptionArguments() const
Definition: CommandAlias.h:64
void SetHelp(llvm::StringRef str) override
void SetHelpLong(llvm::StringRef str) override
std::optional< llvm::StringRef > FindString(llvm::StringRef input_str) const
static const char g_repeat_char
llvm::StringRef GetStringAtIndex(size_t idx) const
void AppendString(llvm::StringRef str, bool reject_if_dupe=true)
void SetStopOnContinue(bool stop_on_continue)
bool IsResult(lldb::CommandInterpreterResult result)
void SetResult(lldb::CommandInterpreterResult result)
bool EchoCommandNonInteractive(llvm::StringRef line, const Flags &io_handler_flags) const
void UpdatePrompt(llvm::StringRef prompt)
bool IOHandlerInterrupt(IOHandler &io_handler) override
void SourceInitFileHome(CommandReturnObject &result, bool is_repl)
We will first see if there is an application specific ".lldbinit" file whose name is "~/....
std::optional< std::string > GetAutoSuggestionForCommand(llvm::StringRef line)
Returns the auto-suggestion string that should be added to the given command line.
void IOHandlerInputComplete(IOHandler &io_handler, std::string &line) override
Called when a line or lines have been retrieved.
std::stack< ExecutionContext > m_overriden_exe_contexts
void OutputFormattedHelpText(Stream &strm, llvm::StringRef prefix, llvm::StringRef help_text)
bool Confirm(llvm::StringRef message, bool default_answer)
bool UserMultiwordCommandExists(llvm::StringRef cmd) const
Determine whether a root-level user multiword command with this name exists.
static llvm::StringRef GetStaticBroadcasterClass()
CommandObject * GetAliasCommandObject(llvm::StringRef cmd, StringList *matches=nullptr, StringList *descriptions=nullptr) const
bool RemoveAlias(llvm::StringRef alias_name)
void SetSaveSessionDirectory(llvm::StringRef path)
void SourceInitFile(FileSpec file, CommandReturnObject &result)
CommandAlias * AddAlias(llvm::StringRef alias_name, lldb::CommandObjectSP &command_obj_sp, llvm::StringRef args_string=llvm::StringRef())
int GetCommandNamesMatchingPartialString(const char *cmd_cstr, bool include_aliases, StringList &matches, StringList &descriptions)
void FindCommandsForApropos(llvm::StringRef word, StringList &commands_found, StringList &commands_help, bool search_builtin_commands, bool search_user_commands, bool search_alias_commands, bool search_user_mw_commands)
CommandObject * GetCommandObject(llvm::StringRef cmd, StringList *matches=nullptr, StringList *descriptions=nullptr) const
std::atomic< CommandHandlingState > m_command_state
Status PreprocessCommand(std::string &command)
CommandObject::CommandMap m_alias_dict
CommandObject * ResolveCommandImpl(std::string &command_line, CommandReturnObject &result)
CommandObject::CommandMap m_command_dict
void HandleCompletion(CompletionRequest &request)
CommandInterpreterRunResult m_result
void ResolveCommand(const char *command_line, CommandReturnObject &result)
bool SetQuitExitCode(int exit_code)
Sets the exit code for the quit command.
CommandInterpreterRunResult RunCommandInterpreter(CommandInterpreterRunOptions &options)
bool HandleCommand(const char *command_line, LazyBool add_to_history, const ExecutionContext &override_context, CommandReturnObject &result)
CommandObject::CommandMap m_user_dict
ExecutionContext GetExecutionContext() const
const CommandObject::CommandMap & GetUserCommands() const
CommandObject * GetUserCommandObject(llvm::StringRef cmd, StringList *matches=nullptr, StringList *descriptions=nullptr) const
void SourceInitFileGlobal(CommandReturnObject &result)
bool GetAliasFullName(llvm::StringRef cmd, std::string &full_name) const
CommandObjectMultiword * VerifyUserMultiwordCmdPath(Args &path, bool leaf_is_command, Status &result)
Look up the command pointed to by path encoded in the arguments of the incoming command object.
void HandleCompletionMatches(CompletionRequest &request)
Status AddUserCommand(llvm::StringRef name, const lldb::CommandObjectSP &cmd_sp, bool can_replace)
bool AddCommand(llvm::StringRef name, const lldb::CommandObjectSP &cmd_sp, bool can_replace)
void PrintCommandOutput(IOHandler &io_handler, llvm::StringRef str, bool is_stdout)
bool AliasExists(llvm::StringRef cmd) const
Determine whether an alias command with this name exists.
int GetOptionArgumentPosition(const char *in_string)
Picks the number out of a string of the form "%NNN", otherwise return 0.
void GetHelp(CommandReturnObject &result, uint32_t types=eCommandTypesAllThem)
bool CommandExists(llvm::StringRef cmd) const
Determine whether a root level, built-in command with this name exists.
bool SaveTranscript(CommandReturnObject &result, std::optional< std::string > output_file=std::nullopt)
Save the current debugger session transcript to a file on disk.
int GetQuitExitCode(bool &exited) const
Returns the exit code that the user has specified when running the 'quit' command.
lldb::PlatformSP GetPlatform(bool prefer_target_platform)
void GetPythonCommandsFromIOHandler(const char *prompt, IOHandlerDelegate &delegate, void *baton=nullptr)
lldb::CommandObjectSP GetCommandSPExact(llvm::StringRef cmd, bool include_aliases=false) const
CommandInterpreter(Debugger &debugger, bool synchronous_execution)
const CommandAlias * GetAlias(llvm::StringRef alias_name) const
bool RemoveUser(llvm::StringRef alias_name)
void GetLLDBCommandsFromIOHandler(const char *prompt, IOHandlerDelegate &delegate, void *baton=nullptr)
lldb::CommandObjectSP GetCommandSP(llvm::StringRef cmd, bool include_aliases=true, bool exact=true, StringList *matches=nullptr, StringList *descriptions=nullptr) const
void OutputHelpText(Stream &stream, llvm::StringRef command_word, llvm::StringRef separator, llvm::StringRef help_text, uint32_t max_word_len)
CommandObject * GetCommandObjectForCommand(llvm::StringRef &command_line)
Status PreprocessToken(std::string &token)
bool RemoveUserMultiword(llvm::StringRef multiword_name)
bool UserCommandExists(llvm::StringRef cmd) const
Determine whether a root-level user command with this name exists.
lldb::IOHandlerSP GetIOHandler(bool force_create=false, CommandInterpreterRunOptions *options=nullptr)
const CommandObject::CommandMap & GetUserMultiwordCommands() const
void BuildAliasCommandArgs(CommandObject *alias_cmd_obj, const char *alias_name, Args &cmd_args, std::string &raw_input_string, CommandReturnObject &result)
std::vector< uint32_t > m_command_source_flags
CommandObject * BuildAliasResult(llvm::StringRef alias_name, std::string &raw_input_string, std::string &alias_result, CommandReturnObject &result)
void OverrideExecutionContext(const ExecutionContext &override_context)
const char * ProcessEmbeddedScriptCommands(const char *arg)
void AllowExitCodeOnQuit(bool allow)
Specify if the command interpreter should allow that the user can specify a custom exit code when cal...
CommandObject::CommandMap m_user_mw_dict
StreamString m_transcript_stream
Turn on settings interpreter.save-transcript for LLDB to populate this stream.
void HandleCommandsFromFile(FileSpec &file, const ExecutionContext &context, const CommandInterpreterRunOptions &options, CommandReturnObject &result)
Execute a list of commands from a file.
void SourceInitFileCwd(CommandReturnObject &result)
std::vector< FileSpec > m_command_source_dirs
A stack of directory paths.
void HandleCommands(const StringList &commands, const ExecutionContext &context, const CommandInterpreterRunOptions &options, CommandReturnObject &result)
Execute a list of commands in sequence.
StructuredData::Array m_transcript
Contains a list of handled commands and their details.
bool RemoveCommand(llvm::StringRef cmd, bool force=false)
Remove a command if it is removable (python or regex command).
const StructuredData::Array & GetTranscript() const
const CommandObject::CommandMap & GetAliases() const
Implements dwim-print, a printing command that chooses the most direct, efficient,...
lldb::CommandObjectSP GetSubcommandSPExact(llvm::StringRef sub_cmd) override
CommandObjectMultiword * GetAsMultiwordCommand() override
virtual bool WantsRawCommandString()=0
void SetOriginalCommandString(std::string s)
Set the command input as it appeared in the terminal.
llvm::StringRef GetCommandName() const
bool HelpTextContainsWord(llvm::StringRef search_word, bool search_short_help=true, bool search_long_help=true, bool search_syntax=true, bool search_options=true)
virtual bool IsMultiwordObject()
virtual void Execute(const char *args_string, CommandReturnObject &result)=0
std::map< std::string, lldb::CommandObjectSP, std::less<> > CommandMap
virtual std::optional< std::string > GetRepeatCommand(Args &current_command_args, uint32_t index)
Get the command that appropriate for a "repeat" of the current command.
virtual CommandObject * GetSubcommandObject(llvm::StringRef sub_cmd, StringList *matches=nullptr)
virtual CommandObjectMultiword * GetAsMultiwordCommand()
virtual Options * GetOptions()
void SetSyntax(llvm::StringRef str)
virtual void HandleCompletion(CompletionRequest &request)
This default version handles calling option argument completions and then calls HandleArgumentComplet...
virtual llvm::StringRef GetHelp()
void AppendErrorWithFormatv(const char *format, Args &&... args)
void AppendMessage(llvm::StringRef in_string)
void void AppendError(llvm::StringRef in_string)
void AppendRawError(llvm::StringRef in_string)
void SetStatus(lldb::ReturnStatus status)
std::string GetErrorString(bool with_diagnostics=true)
Return the errors as a string.
void void AppendMessageWithFormatv(const char *format, Args &&... args)
void AppendErrorWithFormat(const char *format,...) __attribute__((format(printf
void AppendMessageWithFormat(const char *format,...) __attribute__((format(printf
void SetDiagnosticIndent(std::optional< uint16_t > indent)
lldb::ReturnStatus GetStatus() const
"lldb/Utility/ArgCompletionRequest.h"
void AddCompletion(llvm::StringRef completion, llvm::StringRef description="", CompletionMode mode=CompletionMode::Normal)
Adds a possible completion string.
void AddCompletions(const StringList &completions)
Adds multiple possible completion strings.
const Args & GetParsedLine() const
void ShiftArguments()
Drops the first argument from the argument list.
void AppendEmptyArgument()
Adds an empty argument at the end of the argument list and moves the cursor to this new argument.
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
Definition: ConstString.h:188
A class to manage flag bits.
Definition: Debugger.h:80
ExecutionContext GetSelectedExecutionContext()
Definition: Debugger.cpp:1103
bool StartEventHandlerThread()
Manually start the global event handler thread.
Definition: Debugger.cpp:2024
void StopEventHandlerThread()
Manually stop the debugger's default event handler.
Definition: Debugger.cpp:2064
void SetAsyncExecution(bool async)
Definition: Debugger.cpp:1018
HostThread SetIOHandlerThread(HostThread &new_thread)
Definition: Debugger.cpp:2176
lldb::FileSP GetInputFileSP()
Definition: Debugger.h:134
bool GetShowInlineDiagnostics() const
Definition: Debugger.cpp:616
bool IsTopIOHandler(const lldb::IOHandlerSP &reader_sp)
Definition: Debugger.cpp:1190
bool IsIOHandlerThreadCurrentThread() const
Definition: Debugger.cpp:2212
uint64_t GetTerminalWidth() const
Definition: Debugger.cpp:367
const char * GetIOHandlerCommandPrefix()
Definition: Debugger.cpp:1212
bool GetUseColor() const
Definition: Debugger.cpp:421
void RunIOHandlerAsync(const lldb::IOHandlerSP &reader_sp, bool cancel_top_handler=true)
Run the given IO handler and return immediately.
Definition: Debugger.cpp:1224
lldb::StreamFileSP GetErrorStreamSP()
Definition: Debugger.h:138
bool GetAutoConfirm() const
Definition: Debugger.cpp:273
PlatformList & GetPlatformList()
Definition: Debugger.h:200
Target & GetDummyTarget()
Definition: Debugger.h:496
void RunIOHandlerSync(const lldb::IOHandlerSP &reader_sp)
Run the given IO handler and block until it's complete.
Definition: Debugger.cpp:1159
lldb::StreamFileSP GetOutputStreamSP()
Definition: Debugger.h:136
ScriptInterpreter * GetScriptInterpreter(bool can_create=true, std::optional< lldb::ScriptLanguage > language={})
Definition: Debugger.cpp:1719
llvm::StringRef GetExternalEditor() const
Definition: Debugger.cpp:410
File & GetOutputFile()
Definition: Debugger.h:142
llvm::StringRef GetPrompt() const
Definition: Debugger.cpp:306
void FlushProcessOutput(Process &process, bool flush_stdout, bool flush_stderr)
Force flushing the process's pending stdout and stderr to the debugger's asynchronous stdout and stde...
Definition: Debugger.cpp:1789
A class that measures elapsed time in an exception safe way.
Definition: Statistics.h:76
void SetUnwindOnError(bool unwind=false)
Definition: Target.h:359
void SetKeepInMemory(bool keep=true)
Definition: Target.h:369
void SetCoerceToId(bool coerce=true)
Definition: Target.h:355
void SetTryAllThreads(bool try_others=true)
Definition: Target.h:392
void SetTimeout(const Timeout< std::micro > &timeout)
Definition: Target.h:380
void SetIgnoreBreakpoints(bool ignore=false)
Definition: Target.h:363
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
StackFrame * GetFramePtr() const
Returns a pointer to the frame object.
Target * GetTargetPtr() const
Returns a pointer to the target object.
bool HasTargetScope() const
Returns true the ExecutionContext object contains a valid target.
Process * GetProcessPtr() const
Returns a pointer to the process object.
A file utility class.
Definition: FileSpec.h:56
void AppendPathComponent(llvm::StringRef component)
Definition: FileSpec.cpp:447
const ConstString & GetFilename() const
Filename string const get accessor.
Definition: FileSpec.h:240
void MakeAbsolute(const FileSpec &dir)
Make the FileSpec absolute by treating it relative to dir.
Definition: FileSpec.cpp:530
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition: FileSpec.cpp:367
FileSpec CopyByRemovingLastPathComponent() const
Definition: FileSpec.cpp:424
void Resolve(llvm::SmallVectorImpl< char > &path)
Resolve path to make it canonical.
bool GetHomeDirectory(llvm::SmallVectorImpl< char > &path) const
Get the user home directory.
int Open(const char *path, int flags, int mode=0600)
Wraps ::open in a platform-independent way.
static FileSystem & Instance()
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: File.cpp:211
@ eOpenOptionReadOnly
Definition: File.h:51
@ eOpenOptionWriteOnly
Definition: File.h:52
@ eOpenOptionCanCreate
Definition: File.h:56
@ eOpenOptionTruncate
Definition: File.h:57
A class to manage flags.
Definition: Flags.h:22
bool Test(ValueType bit) const
Test a single flag bit.
Definition: Flags.h:96
static lldb::thread_t GetCurrentThread()
Get the thread token (the one returned by ThreadCreate when the thread was created) for the calling t...
static bool IsInteractiveGraphicSession()
Check if we're running in an interactive graphical session.
static llvm::Error OpenFileInExternalEditor(llvm::StringRef editor, const FileSpec &file_spec, uint32_t line_no)
A delegate class for use with IOHandler subclasses.
Definition: IOHandler.h:189
lldb::StreamFileSP GetErrorStreamFileSP()
Definition: IOHandler.cpp:107
virtual const char * GetPrompt()
Definition: IOHandler.h:97
std::recursive_mutex & GetOutputMutex()
Definition: IOHandler.h:163
lldb::StreamFileSP GetOutputStreamFileSP()
Definition: IOHandler.cpp:105
bool GetIsInteractive()
Check if the input is being supplied interactively by a user.
Definition: IOHandler.cpp:109
void SetIsDone(bool b)
Definition: IOHandler.h:85
static LanguageSet GetLanguagesSupportingREPLs()
Definition: Language.cpp:432
static const char * GetNameForLanguageType(lldb::LanguageType language)
Definition: Language.cpp:266
A command line option parsing protocol class.
Definition: Options.h:58
bool SupportsLongOption(const char *long_option)
Definition: Options.cpp:362
lldb::PlatformSP GetSelectedPlatform()
Select the active platform.
Definition: Platform.h:1100
A plug-in interface definition class for debugging a process.
Definition: Process.h:343
lldb::StateType GetState()
Get accessor for the current process state.
Definition: Process.cpp:1308
Status Halt(bool clear_thread_plans=false, bool use_run_lock=true)
Halts a running process.
Definition: Process.cpp:3303
lldb::OptionValuePropertiesSP m_collection_sp
bool SetPropertyAtIndex(uint32_t idx, T t, const ExecutionContext *exe_ctx=nullptr) const
void GetValue(Stream &s, bool show_type) const
Definition: Scalar.cpp:156
Duration get() const
Definition: Statistics.h:39
An error handling class.
Definition: Status.h:115
void Clear()
Clear the object state.
Definition: Status.cpp:215
static Status FromErrorStringWithFormat(const char *format,...) __attribute__((format(printf
Definition: Status.cpp:106
static Status FromErrorString(const char *str)
Definition: Status.h:138
static Status static Status FromErrorStringWithFormatv(const char *format, Args &&...args)
Definition: Status.h:148
const char * GetData() const
Definition: StreamString.h:45
llvm::StringRef GetString() const
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
size_t Indent(llvm::StringRef s="")
Indent the current line in the stream.
Definition: Stream.cpp:157
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:134
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition: Stream.cpp:65
size_t PutChar(char ch)
Definition: Stream.cpp:131
size_t EOL()
Output and End of Line character to the stream.
Definition: Stream.cpp:155
void IndentLess(unsigned amount=2)
Decrement the current indentation level.
Definition: Stream.cpp:198
void IndentMore(unsigned amount=2)
Increment the current indentation level.
Definition: Stream.cpp:195
void AppendString(const std::string &s)
Definition: StringList.cpp:43
const char * GetStringAtIndex(size_t idx) const
Definition: StringList.cpp:86
size_t GetSize() const
Definition: StringList.cpp:74
void DeleteStringAtIndex(size_t id)
Definition: StringList.cpp:147
void AddItem(const ObjectSP &item)
std::shared_ptr< Dictionary > DictionarySP
LoadCWDlldbinitFile GetLoadCWDlldbinitFile() const
Definition: Target.cpp:4914
static TargetProperties & GetGlobalProperties()
Definition: Target.cpp:3183
lldb::PlatformSP GetPlatform()
Definition: Target.h:1463
lldb::ExpressionResults EvaluateExpression(llvm::StringRef expression, ExecutionContextScope *exe_scope, lldb::ValueObjectSP &result_valobj_sp, const EvaluateExpressionOptions &options=EvaluateExpressionOptions(), std::string *fixed_expression=nullptr, ValueObject *ctx_obj=nullptr)
Definition: Target.cpp:2790
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition: Log.h:332
size_t FindLongestCommandWord(std::map< std::string, ValueType, std::less<> > &dict)
Definition: CommandObject.h:59
std::shared_ptr< OptionArgVector > OptionArgVectorSP
Definition: Options.h:30
bool StateIsRunningState(lldb::StateType state)
Check if a state represents a state where the process or thread is running.
Definition: State.cpp:68
int AddNamesMatchingPartialString(const std::map< std::string, ValueType, std::less<> > &in_map, llvm::StringRef cmd_str, StringList &matches, StringList *descriptions=nullptr)
Definition: CommandObject.h:37
@ RewriteLine
The full line has been rewritten by the completion.
LoadCWDlldbinitFile
Definition: Target.h:58
@ eLoadCWDlldbinitTrue
Definition: Target.h:59
@ eLoadCWDlldbinitFalse
Definition: Target.h:60
@ eLoadCWDlldbinitWarn
Definition: Target.h:61
const char * toString(AppleArm64ExceptionClass EC)
std::vector< std::tuple< std::string, int, std::string > > OptionArgVector
Definition: Options.h:29
Definition: SBAddress.h:15
@ eSourceFileCompletion
std::shared_ptr< lldb_private::OptionValueProperties > OptionValuePropertiesSP
Definition: lldb-forward.h:387
std::shared_ptr< lldb_private::IOHandler > IOHandlerSP
Definition: lldb-forward.h:361
std::shared_ptr< lldb_private::CommandObject > CommandObjectSP
Definition: lldb-forward.h:333
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
Definition: lldb-forward.h:484
std::unique_ptr< lldb_private::File > FileUP
Definition: lldb-forward.h:352
@ eCommandInterpreterResultInferiorCrash
Stopped because the corresponding option was set and the inferior crashed.
@ eCommandInterpreterResultSuccess
Command interpreter finished successfully.
@ eCommandInterpreterResultCommandError
Stopped because the corresponding option was set and a command returned an error.
@ eCommandInterpreterResultQuitRequested
Stopped because quit was requested.
std::shared_ptr< lldb_private::UnixSignals > UnixSignalsSP
Definition: lldb-forward.h:480
std::shared_ptr< lldb_private::Platform > PlatformSP
Definition: lldb-forward.h:388
StateType
Process and Thread States.
@ eStateStopped
Process or thread is stopped and can be examined.
LanguageType
Programming language type.
@ eLanguageTypeUnknown
Unknown or invalid language value.
ExpressionResults
The results of expression evaluation.
@ eExpressionCompleted
std::shared_ptr< lldb_private::Process > ProcessSP
Definition: lldb-forward.h:389
std::shared_ptr< lldb_private::Event > EventSP
Definition: lldb-forward.h:345
@ eReturnStatusStarted
@ eReturnStatusSuccessContinuingResult
@ eReturnStatusFailed
@ eReturnStatusSuccessContinuingNoResult
@ eReturnStatusQuit
@ eReturnStatusSuccessFinishResult
@ eReturnStatusInvalid
@ eReturnStatusSuccessFinishNoResult
std::shared_ptr< lldb_private::StreamFile > StreamFileSP
Definition: lldb-forward.h:433
std::shared_ptr< lldb_private::StopInfo > StopInfoSP
Definition: lldb-forward.h:431
StopReason
Thread stop reasons.
@ eStopReasonInstrumentation
@ eStopReasonInterrupt
Thread requested interrupt.
@ eStopReasonProcessorTrace
@ eStopReasonException
@ eStopReasonSignal
std::shared_ptr< lldb_private::Target > TargetSP
Definition: lldb-forward.h:448
std::shared_ptr< lldb_private::File > FileSP
Definition: lldb-forward.h:353
const char * c_str() const
Definition: Args.h:51
llvm::StringRef ref() const
Definition: Args.h:50
char GetQuoteChar() const
Definition: Args.h:55
A SmallBitVector that represents a set of source languages (lldb::LanguageType).
Definition: Type.h:38
std::optional< lldb::LanguageType > GetSingularLanguage()
If the set contains a single language only, return it.
Definition: TypeSystem.cpp:28