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 AddAlias("call", cmd_obj_sp, "--")->SetHelpLong("");
445 CommandAlias *parray_alias =
446 AddAlias("parray", cmd_obj_sp, "--element-count %1 --");
447 if (parray_alias) {
448 parray_alias->SetHelp
449 ("parray <COUNT> <EXPRESSION> -- lldb will evaluate EXPRESSION "
450 "to get a typed-pointer-to-an-array in memory, and will display "
451 "COUNT elements of that type from the array.");
452 parray_alias->SetHelpLong("");
453 }
454 CommandAlias *poarray_alias = AddAlias("poarray", cmd_obj_sp,
455 "--object-description --element-count %1 --");
456 if (poarray_alias) {
457 poarray_alias->SetHelp("poarray <COUNT> <EXPRESSION> -- lldb will "
458 "evaluate EXPRESSION to get the address of an array of COUNT "
459 "objects in memory, and will call po on them.");
460 poarray_alias->SetHelpLong("");
461 }
462 }
463
464 cmd_obj_sp = GetCommandSPExact("platform shell");
465 if (cmd_obj_sp) {
466 CommandAlias *shell_alias = AddAlias("shell", cmd_obj_sp, " --host --");
467 if (shell_alias) {
468 shell_alias->SetHelp("Run a shell command on the host.");
469 shell_alias->SetHelpLong("");
470 shell_alias->SetSyntax("shell <shell-command>");
471 }
472 }
473
474 cmd_obj_sp = GetCommandSPExact("process kill");
475 if (cmd_obj_sp) {
476 AddAlias("kill", cmd_obj_sp);
477 }
478
479 cmd_obj_sp = GetCommandSPExact("process launch");
480 if (cmd_obj_sp) {
481 alias_arguments_vector_sp = std::make_shared<OptionArgVector>();
482#if defined(__APPLE__)
483#if TARGET_OS_IPHONE
484 AddAlias("r", cmd_obj_sp, "--");
485 AddAlias("run", cmd_obj_sp, "--");
486#else
487 AddAlias("r", cmd_obj_sp, "--shell-expand-args true --");
488 AddAlias("run", cmd_obj_sp, "--shell-expand-args true --");
489#endif
490#else
491 StreamString defaultshell;
492 defaultshell.Printf("--shell=%s --",
493 HostInfo::GetDefaultShell().GetPath().c_str());
494 AddAlias("r", cmd_obj_sp, defaultshell.GetString());
495 AddAlias("run", cmd_obj_sp, defaultshell.GetString());
496#endif
497 }
498
499 cmd_obj_sp = GetCommandSPExact("target symbols add");
500 if (cmd_obj_sp) {
501 AddAlias("add-dsym", cmd_obj_sp);
502 }
503
504 cmd_obj_sp = GetCommandSPExact("breakpoint set");
505 if (cmd_obj_sp) {
506 AddAlias("rbreak", cmd_obj_sp, "--func-regex %1");
507 }
508
509 cmd_obj_sp = GetCommandSPExact("frame variable");
510 if (cmd_obj_sp) {
511 AddAlias("v", cmd_obj_sp);
512 AddAlias("var", cmd_obj_sp);
513 AddAlias("vo", cmd_obj_sp, "--object-description");
514 }
515
516 cmd_obj_sp = GetCommandSPExact("register");
517 if (cmd_obj_sp) {
518 AddAlias("re", cmd_obj_sp);
519 }
520
521 cmd_obj_sp = GetCommandSPExact("scripting run");
522 if (cmd_obj_sp) {
523 AddAlias("sc", cmd_obj_sp);
524 AddAlias("scr", cmd_obj_sp);
525 AddAlias("scri", cmd_obj_sp);
526 AddAlias("scrip", cmd_obj_sp);
527 AddAlias("script", cmd_obj_sp);
528 }
529
530 cmd_obj_sp = GetCommandSPExact("session history");
531 if (cmd_obj_sp) {
532 AddAlias("history", cmd_obj_sp);
533 }
534
535 cmd_obj_sp = GetCommandSPExact("help");
536 if (cmd_obj_sp) {
537 AddAlias("h", cmd_obj_sp);
538 }
539}
540
543}
544
546 // This function has not yet been implemented.
547
548 // Look for any embedded script command
549 // If found,
550 // get interpreter object from the command dictionary,
551 // call execute_one_command on it,
552 // get the results as a string,
553 // substitute that string for current stuff.
554
555 return arg;
556}
557
558#define REGISTER_COMMAND_OBJECT(NAME, CLASS) \
559 m_command_dict[NAME] = std::make_shared<CLASS>(*this);
560
563
593
594 // clang-format off
595 const char *break_regexes[][2] = {
596 {"^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$",
597 "breakpoint set --file '%1' --line %2 --column %3"},
598 {"^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$",
599 "breakpoint set --file '%1' --line %2"},
600 {"^/([^/]+)/$", "breakpoint set --source-pattern-regexp '%1'"},
601 {"^([[:digit:]]+)[[:space:]]*$", "breakpoint set --line %1"},
602 {"^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "breakpoint set --address %1"},
603 {"^[\"']?([-+]?\\[.*\\])[\"']?[[:space:]]*$",
604 "breakpoint set --name '%1'"},
605 {"^(-.*)$", "breakpoint set %1"},
606 {"^(.*[^[:space:]])`(.*[^[:space:]])[[:space:]]*$",
607 "breakpoint set --name '%2' --shlib '%1'"},
608 {"^\\&(.*[^[:space:]])[[:space:]]*$",
609 "breakpoint set --name '%1' --skip-prologue=0"},
610 {"^[\"']?(.*[^[:space:]\"'])[\"']?[[:space:]]*$",
611 "breakpoint set --name '%1'"}};
612 // clang-format on
613
614 size_t num_regexes = std::size(break_regexes);
615
616 std::unique_ptr<CommandObjectRegexCommand> break_regex_cmd_up(
618 *this, "_regexp-break",
619 "Set a breakpoint using one of several shorthand formats.",
620 "\n"
621 "_regexp-break <filename>:<linenum>:<colnum>\n"
622 " main.c:12:21 // Break at line 12 and column "
623 "21 of main.c\n\n"
624 "_regexp-break <filename>:<linenum>\n"
625 " main.c:12 // Break at line 12 of "
626 "main.c\n\n"
627 "_regexp-break <linenum>\n"
628 " 12 // Break at line 12 of current "
629 "file\n\n"
630 "_regexp-break 0x<address>\n"
631 " 0x1234000 // Break at address "
632 "0x1234000\n\n"
633 "_regexp-break <name>\n"
634 " main // Break in 'main' after the "
635 "prologue\n\n"
636 "_regexp-break &<name>\n"
637 " &main // Break at first instruction "
638 "in 'main'\n\n"
639 "_regexp-break <module>`<name>\n"
640 " libc.so`malloc // Break in 'malloc' from "
641 "'libc.so'\n\n"
642 "_regexp-break /<source-regex>/\n"
643 " /break here/ // Break on source lines in "
644 "current file\n"
645 " // containing text 'break "
646 "here'.\n",
648
649 if (break_regex_cmd_up) {
650 bool success = true;
651 for (size_t i = 0; i < num_regexes; i++) {
652 success = break_regex_cmd_up->AddRegexCommand(break_regexes[i][0],
653 break_regexes[i][1]);
654 if (!success)
655 break;
656 }
657 success =
658 break_regex_cmd_up->AddRegexCommand("^$", "breakpoint list --full");
659
660 if (success) {
661 CommandObjectSP break_regex_cmd_sp(break_regex_cmd_up.release());
662 m_command_dict[std::string(break_regex_cmd_sp->GetCommandName())] =
663 break_regex_cmd_sp;
664 }
665 }
666
667 std::unique_ptr<CommandObjectRegexCommand> tbreak_regex_cmd_up(
669 *this, "_regexp-tbreak",
670 "Set a one-shot breakpoint using one of several shorthand formats.",
671 "\n"
672 "_regexp-break <filename>:<linenum>:<colnum>\n"
673 " main.c:12:21 // Break at line 12 and column "
674 "21 of main.c\n\n"
675 "_regexp-break <filename>:<linenum>\n"
676 " main.c:12 // Break at line 12 of "
677 "main.c\n\n"
678 "_regexp-break <linenum>\n"
679 " 12 // Break at line 12 of current "
680 "file\n\n"
681 "_regexp-break 0x<address>\n"
682 " 0x1234000 // Break at address "
683 "0x1234000\n\n"
684 "_regexp-break <name>\n"
685 " main // Break in 'main' after the "
686 "prologue\n\n"
687 "_regexp-break &<name>\n"
688 " &main // Break at first instruction "
689 "in 'main'\n\n"
690 "_regexp-break <module>`<name>\n"
691 " libc.so`malloc // Break in 'malloc' from "
692 "'libc.so'\n\n"
693 "_regexp-break /<source-regex>/\n"
694 " /break here/ // Break on source lines in "
695 "current file\n"
696 " // containing text 'break "
697 "here'.\n",
699
700 if (tbreak_regex_cmd_up) {
701 bool success = true;
702 for (size_t i = 0; i < num_regexes; i++) {
703 std::string command = break_regexes[i][1];
704 command += " -o 1";
705 success =
706 tbreak_regex_cmd_up->AddRegexCommand(break_regexes[i][0], command);
707 if (!success)
708 break;
709 }
710 success =
711 tbreak_regex_cmd_up->AddRegexCommand("^$", "breakpoint list --full");
712
713 if (success) {
714 CommandObjectSP tbreak_regex_cmd_sp(tbreak_regex_cmd_up.release());
715 m_command_dict[std::string(tbreak_regex_cmd_sp->GetCommandName())] =
716 tbreak_regex_cmd_sp;
717 }
718 }
719
720 std::unique_ptr<CommandObjectRegexCommand> attach_regex_cmd_up(
722 *this, "_regexp-attach", "Attach to process by ID or name.",
723 "_regexp-attach <pid> | <process-name>", 0, false));
724 if (attach_regex_cmd_up) {
725 if (attach_regex_cmd_up->AddRegexCommand("^([0-9]+)[[:space:]]*$",
726 "process attach --pid %1") &&
727 attach_regex_cmd_up->AddRegexCommand(
728 "^(-.*|.* -.*)$", "process attach %1") && // Any options that are
729 // specified get passed to
730 // 'process attach'
731 attach_regex_cmd_up->AddRegexCommand("^(.+)$",
732 "process attach --name '%1'") &&
733 attach_regex_cmd_up->AddRegexCommand("^$", "process attach")) {
734 CommandObjectSP attach_regex_cmd_sp(attach_regex_cmd_up.release());
735 m_command_dict[std::string(attach_regex_cmd_sp->GetCommandName())] =
736 attach_regex_cmd_sp;
737 }
738 }
739
740 std::unique_ptr<CommandObjectRegexCommand> down_regex_cmd_up(
741 new CommandObjectRegexCommand(*this, "_regexp-down",
742 "Select a newer stack frame. Defaults to "
743 "moving one frame, a numeric argument can "
744 "specify an arbitrary number.",
745 "_regexp-down [<count>]", 0, false));
746 if (down_regex_cmd_up) {
747 if (down_regex_cmd_up->AddRegexCommand("^$", "frame select -r -1") &&
748 down_regex_cmd_up->AddRegexCommand("^([0-9]+)$",
749 "frame select -r -%1")) {
750 CommandObjectSP down_regex_cmd_sp(down_regex_cmd_up.release());
751 m_command_dict[std::string(down_regex_cmd_sp->GetCommandName())] =
752 down_regex_cmd_sp;
753 }
754 }
755
756 std::unique_ptr<CommandObjectRegexCommand> up_regex_cmd_up(
758 *this, "_regexp-up",
759 "Select an older stack frame. Defaults to moving one "
760 "frame, a numeric argument can specify an arbitrary number.",
761 "_regexp-up [<count>]", 0, false));
762 if (up_regex_cmd_up) {
763 if (up_regex_cmd_up->AddRegexCommand("^$", "frame select -r 1") &&
764 up_regex_cmd_up->AddRegexCommand("^([0-9]+)$", "frame select -r %1")) {
765 CommandObjectSP up_regex_cmd_sp(up_regex_cmd_up.release());
766 m_command_dict[std::string(up_regex_cmd_sp->GetCommandName())] =
767 up_regex_cmd_sp;
768 }
769 }
770
771 std::unique_ptr<CommandObjectRegexCommand> display_regex_cmd_up(
773 *this, "_regexp-display",
774 "Evaluate an expression at every stop (see 'help target stop-hook'.)",
775 "_regexp-display expression", 0, false));
776 if (display_regex_cmd_up) {
777 if (display_regex_cmd_up->AddRegexCommand(
778 "^(.+)$", "target stop-hook add -o \"expr -- %1\"")) {
779 CommandObjectSP display_regex_cmd_sp(display_regex_cmd_up.release());
780 m_command_dict[std::string(display_regex_cmd_sp->GetCommandName())] =
781 display_regex_cmd_sp;
782 }
783 }
784
785 std::unique_ptr<CommandObjectRegexCommand> undisplay_regex_cmd_up(
786 new CommandObjectRegexCommand(*this, "_regexp-undisplay",
787 "Stop displaying expression at every "
788 "stop (specified by stop-hook index.)",
789 "_regexp-undisplay stop-hook-number", 0,
790 false));
791 if (undisplay_regex_cmd_up) {
792 if (undisplay_regex_cmd_up->AddRegexCommand("^([0-9]+)$",
793 "target stop-hook delete %1")) {
794 CommandObjectSP undisplay_regex_cmd_sp(undisplay_regex_cmd_up.release());
795 m_command_dict[std::string(undisplay_regex_cmd_sp->GetCommandName())] =
796 undisplay_regex_cmd_sp;
797 }
798 }
799
800 std::unique_ptr<CommandObjectRegexCommand> connect_gdb_remote_cmd_up(
802 *this, "gdb-remote",
803 "Connect to a process via remote GDB server.\n"
804 "If no host is specifed, localhost is assumed.\n"
805 "gdb-remote is an abbreviation for 'process connect --plugin "
806 "gdb-remote connect://<hostname>:<port>'\n",
807 "gdb-remote [<hostname>:]<portnum>", 0, false));
808 if (connect_gdb_remote_cmd_up) {
809 if (connect_gdb_remote_cmd_up->AddRegexCommand(
810 "^([^:]+|\\[[0-9a-fA-F:]+.*\\]):([0-9]+)$",
811 "process connect --plugin gdb-remote connect://%1:%2") &&
812 connect_gdb_remote_cmd_up->AddRegexCommand(
813 "^([[:digit:]]+)$",
814 "process connect --plugin gdb-remote connect://localhost:%1")) {
815 CommandObjectSP command_sp(connect_gdb_remote_cmd_up.release());
816 m_command_dict[std::string(command_sp->GetCommandName())] = command_sp;
817 }
818 }
819
820 std::unique_ptr<CommandObjectRegexCommand> connect_kdp_remote_cmd_up(
822 *this, "kdp-remote",
823 "Connect to a process via remote KDP server.\n"
824 "If no UDP port is specified, port 41139 is assumed.\n"
825 "kdp-remote is an abbreviation for 'process connect --plugin "
826 "kdp-remote udp://<hostname>:<port>'\n",
827 "kdp-remote <hostname>[:<portnum>]", 0, false));
828 if (connect_kdp_remote_cmd_up) {
829 if (connect_kdp_remote_cmd_up->AddRegexCommand(
830 "^([^:]+:[[:digit:]]+)$",
831 "process connect --plugin kdp-remote udp://%1") &&
832 connect_kdp_remote_cmd_up->AddRegexCommand(
833 "^(.+)$", "process connect --plugin kdp-remote udp://%1:41139")) {
834 CommandObjectSP command_sp(connect_kdp_remote_cmd_up.release());
835 m_command_dict[std::string(command_sp->GetCommandName())] = command_sp;
836 }
837 }
838
839 std::unique_ptr<CommandObjectRegexCommand> bt_regex_cmd_up(
841 *this, "_regexp-bt",
842 "Show backtrace of the current thread's call stack. Any numeric "
843 "argument displays at most that many frames. The argument 'all' "
844 "displays all threads. Use 'settings set frame-format' to customize "
845 "the printing of individual frames and 'settings set thread-format' "
846 "to customize the thread header.",
847 "bt [<digit> | all]", 0, false));
848 if (bt_regex_cmd_up) {
849 // accept but don't document "bt -c <number>" -- before bt was a regex
850 // command if you wanted to backtrace three frames you would do "bt -c 3"
851 // but the intention is to have this emulate the gdb "bt" command and so
852 // now "bt 3" is the preferred form, in line with gdb.
853 if (bt_regex_cmd_up->AddRegexCommand("^([[:digit:]]+)[[:space:]]*$",
854 "thread backtrace -c %1") &&
855 bt_regex_cmd_up->AddRegexCommand("^-c ([[:digit:]]+)[[:space:]]*$",
856 "thread backtrace -c %1") &&
857 bt_regex_cmd_up->AddRegexCommand("^all[[:space:]]*$", "thread backtrace all") &&
858 bt_regex_cmd_up->AddRegexCommand("^[[:space:]]*$", "thread backtrace")) {
859 CommandObjectSP command_sp(bt_regex_cmd_up.release());
860 m_command_dict[std::string(command_sp->GetCommandName())] = command_sp;
861 }
862 }
863
864 std::unique_ptr<CommandObjectRegexCommand> list_regex_cmd_up(
866 *this, "_regexp-list",
867 "List relevant source code using one of several shorthand formats.",
868 "\n"
869 "_regexp-list <file>:<line> // List around specific file/line\n"
870 "_regexp-list <line> // List current file around specified "
871 "line\n"
872 "_regexp-list <function-name> // List specified function\n"
873 "_regexp-list 0x<address> // List around specified address\n"
874 "_regexp-list -[<count>] // List previous <count> lines\n"
875 "_regexp-list // List subsequent lines",
877 if (list_regex_cmd_up) {
878 if (list_regex_cmd_up->AddRegexCommand("^([0-9]+)[[:space:]]*$",
879 "source list --line %1") &&
880 list_regex_cmd_up->AddRegexCommand(
881 "^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]"
882 "]*$",
883 "source list --file '%1' --line %2") &&
884 list_regex_cmd_up->AddRegexCommand(
885 "^\\*?(0x[[:xdigit:]]+)[[:space:]]*$",
886 "source list --address %1") &&
887 list_regex_cmd_up->AddRegexCommand("^-[[:space:]]*$",
888 "source list --reverse") &&
889 list_regex_cmd_up->AddRegexCommand(
890 "^-([[:digit:]]+)[[:space:]]*$",
891 "source list --reverse --count %1") &&
892 list_regex_cmd_up->AddRegexCommand("^(.+)$",
893 "source list --name \"%1\"") &&
894 list_regex_cmd_up->AddRegexCommand("^$", "source list")) {
895 CommandObjectSP list_regex_cmd_sp(list_regex_cmd_up.release());
896 m_command_dict[std::string(list_regex_cmd_sp->GetCommandName())] =
897 list_regex_cmd_sp;
898 }
899 }
900
901 std::unique_ptr<CommandObjectRegexCommand> env_regex_cmd_up(
903 *this, "_regexp-env",
904 "Shorthand for viewing and setting environment variables.",
905 "\n"
906 "_regexp-env // Show environment\n"
907 "_regexp-env <name>=<value> // Set an environment variable",
908 0, false));
909 if (env_regex_cmd_up) {
910 if (env_regex_cmd_up->AddRegexCommand("^$",
911 "settings show target.env-vars") &&
912 env_regex_cmd_up->AddRegexCommand("^([A-Za-z_][A-Za-z_0-9]*=.*)$",
913 "settings set target.env-vars %1")) {
914 CommandObjectSP env_regex_cmd_sp(env_regex_cmd_up.release());
915 m_command_dict[std::string(env_regex_cmd_sp->GetCommandName())] =
916 env_regex_cmd_sp;
917 }
918 }
919
920 std::unique_ptr<CommandObjectRegexCommand> jump_regex_cmd_up(
922 *this, "_regexp-jump", "Set the program counter to a new address.",
923 "\n"
924 "_regexp-jump <line>\n"
925 "_regexp-jump +<line-offset> | -<line-offset>\n"
926 "_regexp-jump <file>:<line>\n"
927 "_regexp-jump *<addr>\n",
928 0, false));
929 if (jump_regex_cmd_up) {
930 if (jump_regex_cmd_up->AddRegexCommand("^\\*(.*)$",
931 "thread jump --addr %1") &&
932 jump_regex_cmd_up->AddRegexCommand("^([0-9]+)$",
933 "thread jump --line %1") &&
934 jump_regex_cmd_up->AddRegexCommand("^([^:]+):([0-9]+)$",
935 "thread jump --file %1 --line %2") &&
936 jump_regex_cmd_up->AddRegexCommand("^([+\\-][0-9]+)$",
937 "thread jump --by %1")) {
938 CommandObjectSP jump_regex_cmd_sp(jump_regex_cmd_up.release());
939 m_command_dict[std::string(jump_regex_cmd_sp->GetCommandName())] =
940 jump_regex_cmd_sp;
941 }
942 }
943}
944
946 const char *cmd_str, bool include_aliases, StringList &matches,
947 StringList &descriptions) {
949 &descriptions);
950
951 if (include_aliases) {
953 &descriptions);
954 }
955
956 return matches.GetSize();
957}
958
960 Args &path, bool leaf_is_command, Status &result) {
961 result.Clear();
962
963 auto get_multi_or_report_error =
964 [&result](CommandObjectSP cmd_sp,
965 const char *name) -> CommandObjectMultiword * {
966 if (!cmd_sp) {
967 result.SetErrorStringWithFormat("Path component: '%s' not found", name);
968 return nullptr;
969 }
970 if (!cmd_sp->IsUserCommand()) {
971 result.SetErrorStringWithFormat("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) {
978 result.SetErrorStringWithFormat("Path component: '%s' is not a container "
979 "command",
980 name);
981 return nullptr;
982 }
983 return cmd_as_multi;
984 };
985
986 size_t num_args = path.GetArgumentCount();
987 if (num_args == 0) {
988 result.SetErrorString("empty command path");
989 return nullptr;
990 }
991
992 if (num_args == 1 && leaf_is_command) {
993 // We just got a leaf command to be added to the root. That's not an error,
994 // just return null for the container.
995 return nullptr;
996 }
997
998 // Start by getting the root command from the interpreter.
999 const char *cur_name = path.GetArgumentAtIndex(0);
1000 CommandObjectSP cur_cmd_sp = GetCommandSPExact(cur_name);
1001 CommandObjectMultiword *cur_as_multi =
1002 get_multi_or_report_error(cur_cmd_sp, cur_name);
1003 if (cur_as_multi == nullptr)
1004 return nullptr;
1005
1006 size_t num_path_elements = num_args - (leaf_is_command ? 1 : 0);
1007 for (size_t cursor = 1; cursor < num_path_elements && cur_as_multi != nullptr;
1008 cursor++) {
1009 cur_name = path.GetArgumentAtIndex(cursor);
1010 cur_cmd_sp = cur_as_multi->GetSubcommandSPExact(cur_name);
1011 cur_as_multi = get_multi_or_report_error(cur_cmd_sp, cur_name);
1012 }
1013 return cur_as_multi;
1014}
1015
1017CommandInterpreter::GetCommandSP(llvm::StringRef cmd_str, bool include_aliases,
1018 bool exact, StringList *matches,
1019 StringList *descriptions) const {
1020 CommandObjectSP command_sp;
1021
1022 std::string cmd = std::string(cmd_str);
1023
1024 if (HasCommands()) {
1025 auto pos = m_command_dict.find(cmd);
1026 if (pos != m_command_dict.end())
1027 command_sp = pos->second;
1028 }
1029
1030 if (include_aliases && HasAliases()) {
1031 auto alias_pos = m_alias_dict.find(cmd);
1032 if (alias_pos != m_alias_dict.end())
1033 command_sp = alias_pos->second;
1034 }
1035
1036 if (HasUserCommands()) {
1037 auto pos = m_user_dict.find(cmd);
1038 if (pos != m_user_dict.end())
1039 command_sp = pos->second;
1040 }
1041
1043 auto pos = m_user_mw_dict.find(cmd);
1044 if (pos != m_user_mw_dict.end())
1045 command_sp = pos->second;
1046 }
1047
1048 if (!exact && !command_sp) {
1049 // We will only get into here if we didn't find any exact matches.
1050
1051 CommandObjectSP user_match_sp, user_mw_match_sp, alias_match_sp,
1052 real_match_sp;
1053
1054 StringList local_matches;
1055 if (matches == nullptr)
1056 matches = &local_matches;
1057
1058 unsigned int num_cmd_matches = 0;
1059 unsigned int num_alias_matches = 0;
1060 unsigned int num_user_matches = 0;
1061 unsigned int num_user_mw_matches = 0;
1062
1063 // Look through the command dictionaries one by one, and if we get only one
1064 // match from any of them in toto, then return that, otherwise return an
1065 // empty CommandObjectSP and the list of matches.
1066
1067 if (HasCommands()) {
1068 num_cmd_matches = AddNamesMatchingPartialString(m_command_dict, cmd_str,
1069 *matches, descriptions);
1070 }
1071
1072 if (num_cmd_matches == 1) {
1073 cmd.assign(matches->GetStringAtIndex(0));
1074 auto pos = m_command_dict.find(cmd);
1075 if (pos != m_command_dict.end())
1076 real_match_sp = pos->second;
1077 }
1078
1079 if (include_aliases && HasAliases()) {
1080 num_alias_matches = AddNamesMatchingPartialString(m_alias_dict, cmd_str,
1081 *matches, descriptions);
1082 }
1083
1084 if (num_alias_matches == 1) {
1085 cmd.assign(matches->GetStringAtIndex(num_cmd_matches));
1086 auto alias_pos = m_alias_dict.find(cmd);
1087 if (alias_pos != m_alias_dict.end())
1088 alias_match_sp = alias_pos->second;
1089 }
1090
1091 if (HasUserCommands()) {
1092 num_user_matches = AddNamesMatchingPartialString(m_user_dict, cmd_str,
1093 *matches, descriptions);
1094 }
1095
1096 if (num_user_matches == 1) {
1097 cmd.assign(
1098 matches->GetStringAtIndex(num_cmd_matches + num_alias_matches));
1099
1100 auto pos = m_user_dict.find(cmd);
1101 if (pos != m_user_dict.end())
1102 user_match_sp = pos->second;
1103 }
1104
1106 num_user_mw_matches = AddNamesMatchingPartialString(
1107 m_user_mw_dict, cmd_str, *matches, descriptions);
1108 }
1109
1110 if (num_user_mw_matches == 1) {
1111 cmd.assign(matches->GetStringAtIndex(num_cmd_matches + num_alias_matches +
1112 num_user_matches));
1113
1114 auto pos = m_user_mw_dict.find(cmd);
1115 if (pos != m_user_mw_dict.end())
1116 user_mw_match_sp = pos->second;
1117 }
1118
1119 // If we got exactly one match, return that, otherwise return the match
1120 // list.
1121
1122 if (num_user_matches + num_user_mw_matches + num_cmd_matches +
1123 num_alias_matches ==
1124 1) {
1125 if (num_cmd_matches)
1126 return real_match_sp;
1127 else if (num_alias_matches)
1128 return alias_match_sp;
1129 else if (num_user_mw_matches)
1130 return user_mw_match_sp;
1131 else
1132 return user_match_sp;
1133 }
1134 } else if (matches && command_sp) {
1135 matches->AppendString(cmd_str);
1136 if (descriptions)
1137 descriptions->AppendString(command_sp->GetHelp());
1138 }
1139
1140 return command_sp;
1141}
1142
1143bool CommandInterpreter::AddCommand(llvm::StringRef name,
1144 const lldb::CommandObjectSP &cmd_sp,
1145 bool can_replace) {
1146 if (cmd_sp.get())
1147 lldbassert((this == &cmd_sp->GetCommandInterpreter()) &&
1148 "tried to add a CommandObject from a different interpreter");
1149
1150 if (name.empty())
1151 return false;
1152
1153 cmd_sp->SetIsUserCommand(false);
1154
1155 std::string name_sstr(name);
1156 auto name_iter = m_command_dict.find(name_sstr);
1157 if (name_iter != m_command_dict.end()) {
1158 if (!can_replace || !name_iter->second->IsRemovable())
1159 return false;
1160 name_iter->second = cmd_sp;
1161 } else {
1162 m_command_dict[name_sstr] = cmd_sp;
1163 }
1164 return true;
1165}
1166
1168 const lldb::CommandObjectSP &cmd_sp,
1169 bool can_replace) {
1170 Status result;
1171 if (cmd_sp.get())
1172 lldbassert((this == &cmd_sp->GetCommandInterpreter()) &&
1173 "tried to add a CommandObject from a different interpreter");
1174 if (name.empty()) {
1175 result.SetErrorString("can't use the empty string for a command name");
1176 return result;
1177 }
1178 // do not allow replacement of internal commands
1179 if (CommandExists(name)) {
1180 result.SetErrorString("can't replace builtin command");
1181 return result;
1182 }
1183
1184 if (UserCommandExists(name)) {
1185 if (!can_replace) {
1187 "user command \"{0}\" already exists and force replace was not set "
1188 "by --overwrite or 'settings set interpreter.require-overwrite "
1189 "false'",
1190 name);
1191 return result;
1192 }
1193 if (cmd_sp->IsMultiwordObject()) {
1194 if (!m_user_mw_dict[std::string(name)]->IsRemovable()) {
1195 result.SetErrorString(
1196 "can't replace explicitly non-removable multi-word command");
1197 return result;
1198 }
1199 } else {
1200 if (!m_user_dict[std::string(name)]->IsRemovable()) {
1201 result.SetErrorString("can't replace explicitly non-removable command");
1202 return result;
1203 }
1204 }
1205 }
1206
1207 cmd_sp->SetIsUserCommand(true);
1208
1209 if (cmd_sp->IsMultiwordObject())
1210 m_user_mw_dict[std::string(name)] = cmd_sp;
1211 else
1212 m_user_dict[std::string(name)] = cmd_sp;
1213 return result;
1214}
1215
1218 bool include_aliases) const {
1219 // Break up the command string into words, in case it's a multi-word command.
1220 Args cmd_words(cmd_str);
1221
1222 if (cmd_str.empty())
1223 return {};
1224
1225 if (cmd_words.GetArgumentCount() == 1)
1226 return GetCommandSP(cmd_str, include_aliases, true);
1227
1228 // We have a multi-word command (seemingly), so we need to do more work.
1229 // First, get the cmd_obj_sp for the first word in the command.
1230 CommandObjectSP cmd_obj_sp =
1231 GetCommandSP(cmd_words.GetArgumentAtIndex(0), include_aliases, true);
1232 if (!cmd_obj_sp)
1233 return {};
1234
1235 // Loop through the rest of the words in the command (everything passed in
1236 // was supposed to be part of a command name), and find the appropriate
1237 // sub-command SP for each command word....
1238 size_t end = cmd_words.GetArgumentCount();
1239 for (size_t i = 1; i < end; ++i) {
1240 if (!cmd_obj_sp->IsMultiwordObject()) {
1241 // We have more words in the command name, but we don't have a
1242 // multiword object. Fail and return.
1243 return {};
1244 }
1245
1246 cmd_obj_sp = cmd_obj_sp->GetSubcommandSP(cmd_words.GetArgumentAtIndex(i));
1247 if (!cmd_obj_sp) {
1248 // The sub-command name was invalid. Fail and return.
1249 return {};
1250 }
1251 }
1252
1253 // We successfully looped through all the command words and got valid
1254 // command objects for them.
1255 return cmd_obj_sp;
1256}
1257
1260 StringList *matches,
1261 StringList *descriptions) const {
1262 // Try to find a match among commands and aliases. Allowing inexact matches,
1263 // but perferring exact matches.
1264 return GetCommandSP(cmd_str, /*include_aliases=*/true, /*exact=*/false,
1265 matches, descriptions)
1266 .get();
1267}
1268
1270 llvm::StringRef cmd, StringList *matches, StringList *descriptions) const {
1271 std::string cmd_str(cmd);
1272 auto find_exact = [&](const CommandObject::CommandMap &map) {
1273 auto found_elem = map.find(std::string(cmd));
1274 if (found_elem == map.end())
1275 return (CommandObject *)nullptr;
1276 CommandObject *exact_cmd = found_elem->second.get();
1277 if (exact_cmd) {
1278 if (matches)
1279 matches->AppendString(exact_cmd->GetCommandName());
1280 if (descriptions)
1281 descriptions->AppendString(exact_cmd->GetHelp());
1282 return exact_cmd;
1283 }
1284 return (CommandObject *)nullptr;
1285 };
1286
1287 CommandObject *exact_cmd = find_exact(GetUserCommands());
1288 if (exact_cmd)
1289 return exact_cmd;
1290
1291 exact_cmd = find_exact(GetUserMultiwordCommands());
1292 if (exact_cmd)
1293 return exact_cmd;
1294
1295 // We didn't have an exact command, so now look for partial matches.
1296 StringList tmp_list;
1297 StringList *matches_ptr = matches ? matches : &tmp_list;
1298 AddNamesMatchingPartialString(GetUserCommands(), cmd_str, *matches_ptr);
1300 cmd_str, *matches_ptr);
1301
1302 return {};
1303}
1304
1305bool CommandInterpreter::CommandExists(llvm::StringRef cmd) const {
1306 return m_command_dict.find(std::string(cmd)) != m_command_dict.end();
1307}
1308
1310 std::string &full_name) const {
1311 bool exact_match =
1312 (m_alias_dict.find(std::string(cmd)) != m_alias_dict.end());
1313 if (exact_match) {
1314 full_name.assign(std::string(cmd));
1315 return exact_match;
1316 } else {
1317 StringList matches;
1318 size_t num_alias_matches;
1319 num_alias_matches =
1321 if (num_alias_matches == 1) {
1322 // Make sure this isn't shadowing a command in the regular command space:
1323 StringList regular_matches;
1324 const bool include_aliases = false;
1325 const bool exact = false;
1326 CommandObjectSP cmd_obj_sp(
1327 GetCommandSP(cmd, include_aliases, exact, &regular_matches));
1328 if (cmd_obj_sp || regular_matches.GetSize() > 0)
1329 return false;
1330 else {
1331 full_name.assign(matches.GetStringAtIndex(0));
1332 return true;
1333 }
1334 } else
1335 return false;
1336 }
1337}
1338
1339bool CommandInterpreter::AliasExists(llvm::StringRef cmd) const {
1340 return m_alias_dict.find(std::string(cmd)) != m_alias_dict.end();
1341}
1342
1343bool CommandInterpreter::UserCommandExists(llvm::StringRef cmd) const {
1344 return m_user_dict.find(std::string(cmd)) != m_user_dict.end();
1345}
1346
1347bool CommandInterpreter::UserMultiwordCommandExists(llvm::StringRef cmd) const {
1348 return m_user_mw_dict.find(std::string(cmd)) != m_user_mw_dict.end();
1349}
1350
1352CommandInterpreter::AddAlias(llvm::StringRef alias_name,
1353 lldb::CommandObjectSP &command_obj_sp,
1354 llvm::StringRef args_string) {
1355 if (command_obj_sp.get())
1356 lldbassert((this == &command_obj_sp->GetCommandInterpreter()) &&
1357 "tried to add a CommandObject from a different interpreter");
1358
1359 std::unique_ptr<CommandAlias> command_alias_up(
1360 new CommandAlias(*this, command_obj_sp, args_string, alias_name));
1361
1362 if (command_alias_up && command_alias_up->IsValid()) {
1363 m_alias_dict[std::string(alias_name)] =
1364 CommandObjectSP(command_alias_up.get());
1365 return command_alias_up.release();
1366 }
1367
1368 return nullptr;
1369}
1370
1371bool CommandInterpreter::RemoveAlias(llvm::StringRef alias_name) {
1372 auto pos = m_alias_dict.find(std::string(alias_name));
1373 if (pos != m_alias_dict.end()) {
1374 m_alias_dict.erase(pos);
1375 return true;
1376 }
1377 return false;
1378}
1379
1380bool CommandInterpreter::RemoveCommand(llvm::StringRef cmd, bool force) {
1381 auto pos = m_command_dict.find(std::string(cmd));
1382 if (pos != m_command_dict.end()) {
1383 if (force || pos->second->IsRemovable()) {
1384 // Only regular expression objects or python commands are removable under
1385 // normal circumstances.
1386 m_command_dict.erase(pos);
1387 return true;
1388 }
1389 }
1390 return false;
1391}
1392
1393bool CommandInterpreter::RemoveUser(llvm::StringRef user_name) {
1394 CommandObject::CommandMap::iterator pos =
1395 m_user_dict.find(std::string(user_name));
1396 if (pos != m_user_dict.end()) {
1397 m_user_dict.erase(pos);
1398 return true;
1399 }
1400 return false;
1401}
1402
1403bool CommandInterpreter::RemoveUserMultiword(llvm::StringRef multi_name) {
1404 CommandObject::CommandMap::iterator pos =
1405 m_user_mw_dict.find(std::string(multi_name));
1406 if (pos != m_user_mw_dict.end()) {
1407 m_user_mw_dict.erase(pos);
1408 return true;
1409 }
1410 return false;
1411}
1412
1414 uint32_t cmd_types) {
1415 llvm::StringRef help_prologue(GetDebugger().GetIOHandlerHelpPrologue());
1416 if (!help_prologue.empty()) {
1417 OutputFormattedHelpText(result.GetOutputStream(), llvm::StringRef(),
1418 help_prologue);
1419 }
1420
1421 CommandObject::CommandMap::const_iterator pos;
1422 size_t max_len = FindLongestCommandWord(m_command_dict);
1423
1424 if ((cmd_types & eCommandTypesBuiltin) == eCommandTypesBuiltin) {
1425 result.AppendMessage("Debugger commands:");
1426 result.AppendMessage("");
1427
1428 for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos) {
1429 if (!(cmd_types & eCommandTypesHidden) &&
1430 (pos->first.compare(0, 1, "_") == 0))
1431 continue;
1432
1433 OutputFormattedHelpText(result.GetOutputStream(), pos->first, "--",
1434 pos->second->GetHelp(), max_len);
1435 }
1436 result.AppendMessage("");
1437 }
1438
1439 if (!m_alias_dict.empty() &&
1440 ((cmd_types & eCommandTypesAliases) == eCommandTypesAliases)) {
1442 "Current command abbreviations "
1443 "(type '%shelp command alias' for more info):\n",
1445 result.AppendMessage("");
1447
1448 for (auto alias_pos = m_alias_dict.begin(); alias_pos != m_alias_dict.end();
1449 ++alias_pos) {
1450 OutputFormattedHelpText(result.GetOutputStream(), alias_pos->first, "--",
1451 alias_pos->second->GetHelp(), max_len);
1452 }
1453 result.AppendMessage("");
1454 }
1455
1456 if (!m_user_dict.empty() &&
1457 ((cmd_types & eCommandTypesUserDef) == eCommandTypesUserDef)) {
1458 result.AppendMessage("Current user-defined commands:");
1459 result.AppendMessage("");
1461 for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos) {
1462 OutputFormattedHelpText(result.GetOutputStream(), pos->first, "--",
1463 pos->second->GetHelp(), max_len);
1464 }
1465 result.AppendMessage("");
1466 }
1467
1468 if (!m_user_mw_dict.empty() &&
1469 ((cmd_types & eCommandTypesUserMW) == eCommandTypesUserMW)) {
1470 result.AppendMessage("Current user-defined container commands:");
1471 result.AppendMessage("");
1473 for (pos = m_user_mw_dict.begin(); pos != m_user_mw_dict.end(); ++pos) {
1474 OutputFormattedHelpText(result.GetOutputStream(), pos->first, "--",
1475 pos->second->GetHelp(), max_len);
1476 }
1477 result.AppendMessage("");
1478 }
1479
1481 "For more information on any command, type '%shelp <command-name>'.\n",
1483}
1484
1486 llvm::StringRef &command_string) {
1487 // This function finds the final, lowest-level, alias-resolved command object
1488 // whose 'Execute' function will eventually be invoked by the given command
1489 // line.
1490
1491 CommandObject *cmd_obj = nullptr;
1492 size_t start = command_string.find_first_not_of(k_white_space);
1493 size_t end = 0;
1494 bool done = false;
1495 while (!done) {
1496 if (start != std::string::npos) {
1497 // Get the next word from command_string.
1498 end = command_string.find_first_of(k_white_space, start);
1499 if (end == std::string::npos)
1500 end = command_string.size();
1501 std::string cmd_word =
1502 std::string(command_string.substr(start, end - start));
1503
1504 if (cmd_obj == nullptr)
1505 // Since cmd_obj is NULL we are on our first time through this loop.
1506 // Check to see if cmd_word is a valid command or alias.
1507 cmd_obj = GetCommandObject(cmd_word);
1508 else if (cmd_obj->IsMultiwordObject()) {
1509 // Our current object is a multi-word object; see if the cmd_word is a
1510 // valid sub-command for our object.
1511 CommandObject *sub_cmd_obj =
1512 cmd_obj->GetSubcommandObject(cmd_word.c_str());
1513 if (sub_cmd_obj)
1514 cmd_obj = sub_cmd_obj;
1515 else // cmd_word was not a valid sub-command word, so we are done
1516 done = true;
1517 } else
1518 // We have a cmd_obj and it is not a multi-word object, so we are done.
1519 done = true;
1520
1521 // If we didn't find a valid command object, or our command object is not
1522 // a multi-word object, or we are at the end of the command_string, then
1523 // we are done. Otherwise, find the start of the next word.
1524
1525 if (!cmd_obj || !cmd_obj->IsMultiwordObject() ||
1526 end >= command_string.size())
1527 done = true;
1528 else
1529 start = command_string.find_first_not_of(k_white_space, end);
1530 } else
1531 // Unable to find any more words.
1532 done = true;
1533 }
1534
1535 command_string = command_string.substr(end);
1536 return cmd_obj;
1537}
1538
1539static const char *k_valid_command_chars =
1540 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
1541static void StripLeadingSpaces(std::string &s) {
1542 if (!s.empty()) {
1543 size_t pos = s.find_first_not_of(k_white_space);
1544 if (pos == std::string::npos)
1545 s.clear();
1546 else if (pos == 0)
1547 return;
1548 s.erase(0, pos);
1549 }
1550}
1551
1552static size_t FindArgumentTerminator(const std::string &s) {
1553 const size_t s_len = s.size();
1554 size_t offset = 0;
1555 while (offset < s_len) {
1556 size_t pos = s.find("--", offset);
1557 if (pos == std::string::npos)
1558 break;
1559 if (pos > 0) {
1560 if (llvm::isSpace(s[pos - 1])) {
1561 // Check if the string ends "\s--" (where \s is a space character) or
1562 // if we have "\s--\s".
1563 if ((pos + 2 >= s_len) || llvm::isSpace(s[pos + 2])) {
1564 return pos;
1565 }
1566 }
1567 }
1568 offset = pos + 2;
1569 }
1570 return std::string::npos;
1571}
1572
1573static bool ExtractCommand(std::string &command_string, std::string &command,
1574 std::string &suffix, char &quote_char) {
1575 command.clear();
1576 suffix.clear();
1577 StripLeadingSpaces(command_string);
1578
1579 bool result = false;
1580 quote_char = '\0';
1581
1582 if (!command_string.empty()) {
1583 const char first_char = command_string[0];
1584 if (first_char == '\'' || first_char == '"') {
1585 quote_char = first_char;
1586 const size_t end_quote_pos = command_string.find(quote_char, 1);
1587 if (end_quote_pos == std::string::npos) {
1588 command.swap(command_string);
1589 command_string.erase();
1590 } else {
1591 command.assign(command_string, 1, end_quote_pos - 1);
1592 if (end_quote_pos + 1 < command_string.size())
1593 command_string.erase(0, command_string.find_first_not_of(
1594 k_white_space, end_quote_pos + 1));
1595 else
1596 command_string.erase();
1597 }
1598 } else {
1599 const size_t first_space_pos =
1600 command_string.find_first_of(k_white_space);
1601 if (first_space_pos == std::string::npos) {
1602 command.swap(command_string);
1603 command_string.erase();
1604 } else {
1605 command.assign(command_string, 0, first_space_pos);
1606 command_string.erase(0, command_string.find_first_not_of(
1607 k_white_space, first_space_pos));
1608 }
1609 }
1610 result = true;
1611 }
1612
1613 if (!command.empty()) {
1614 // actual commands can't start with '-' or '_'
1615 if (command[0] != '-' && command[0] != '_') {
1616 size_t pos = command.find_first_not_of(k_valid_command_chars);
1617 if (pos > 0 && pos != std::string::npos) {
1618 suffix.assign(command.begin() + pos, command.end());
1619 command.erase(pos);
1620 }
1621 }
1622 }
1623
1624 return result;
1625}
1626
1628 llvm::StringRef alias_name, std::string &raw_input_string,
1629 std::string &alias_result, CommandReturnObject &result) {
1630 CommandObject *alias_cmd_obj = nullptr;
1631 Args cmd_args(raw_input_string);
1632 alias_cmd_obj = GetCommandObject(alias_name);
1633 StreamString result_str;
1634
1635 if (!alias_cmd_obj || !alias_cmd_obj->IsAlias()) {
1636 alias_result.clear();
1637 return alias_cmd_obj;
1638 }
1639 std::pair<CommandObjectSP, OptionArgVectorSP> desugared =
1640 ((CommandAlias *)alias_cmd_obj)->Desugar();
1641 OptionArgVectorSP option_arg_vector_sp = desugared.second;
1642 alias_cmd_obj = desugared.first.get();
1643 std::string alias_name_str = std::string(alias_name);
1644 if ((cmd_args.GetArgumentCount() == 0) ||
1645 (alias_name_str != cmd_args.GetArgumentAtIndex(0)))
1646 cmd_args.Unshift(alias_name_str);
1647
1648 result_str.Printf("%s", alias_cmd_obj->GetCommandName().str().c_str());
1649
1650 if (!option_arg_vector_sp.get()) {
1651 alias_result = std::string(result_str.GetString());
1652 return alias_cmd_obj;
1653 }
1654 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
1655
1656 int value_type;
1657 std::string option;
1658 std::string value;
1659 for (const auto &entry : *option_arg_vector) {
1660 std::tie(option, value_type, value) = entry;
1661 if (option == g_argument) {
1662 result_str.Printf(" %s", value.c_str());
1663 continue;
1664 }
1665
1666 result_str.Printf(" %s", option.c_str());
1667 if (value_type == OptionParser::eNoArgument)
1668 continue;
1669
1670 if (value_type != OptionParser::eOptionalArgument)
1671 result_str.Printf(" ");
1672 int index = GetOptionArgumentPosition(value.c_str());
1673 if (index == 0)
1674 result_str.Printf("%s", value.c_str());
1675 else if (static_cast<size_t>(index) >= cmd_args.GetArgumentCount()) {
1676
1677 result.AppendErrorWithFormat("Not enough arguments provided; you "
1678 "need at least %d arguments to use "
1679 "this alias.\n",
1680 index);
1681 return nullptr;
1682 } else {
1683 const Args::ArgEntry &entry = cmd_args[index];
1684 size_t strpos = raw_input_string.find(entry.c_str());
1685 const char quote_char = entry.GetQuoteChar();
1686 if (strpos != std::string::npos) {
1687 const size_t start_fudge = quote_char == '\0' ? 0 : 1;
1688 const size_t len_fudge = quote_char == '\0' ? 0 : 2;
1689
1690 // Make sure we aren't going outside the bounds of the cmd string:
1691 if (strpos < start_fudge) {
1692 result.AppendError("Unmatched quote at command beginning.");
1693 return nullptr;
1694 }
1695 llvm::StringRef arg_text = entry.ref();
1696 if (strpos - start_fudge + arg_text.size() + len_fudge >
1697 raw_input_string.size()) {
1698 result.AppendError("Unmatched quote at command end.");
1699 return nullptr;
1700 }
1701 raw_input_string = raw_input_string.erase(
1702 strpos - start_fudge,
1703 strlen(cmd_args.GetArgumentAtIndex(index)) + len_fudge);
1704 }
1705 if (quote_char == '\0')
1706 result_str.Printf("%s", cmd_args.GetArgumentAtIndex(index));
1707 else
1708 result_str.Printf("%c%s%c", quote_char, entry.c_str(), quote_char);
1709 }
1710 }
1711
1712 alias_result = std::string(result_str.GetString());
1713 return alias_cmd_obj;
1714}
1715
1717 // The command preprocessor needs to do things to the command line before any
1718 // parsing of arguments or anything else is done. The only current stuff that
1719 // gets preprocessed is anything enclosed in backtick ('`') characters is
1720 // evaluated as an expression and the result of the expression must be a
1721 // scalar that can be substituted into the command. An example would be:
1722 // (lldb) memory read `$rsp + 20`
1723 Status error; // Status for any expressions that might not evaluate
1724 size_t start_backtick;
1725 size_t pos = 0;
1726 while ((start_backtick = command.find('`', pos)) != std::string::npos) {
1727 // Stop if an error was encountered during the previous iteration.
1728 if (error.Fail())
1729 break;
1730
1731 if (start_backtick > 0 && command[start_backtick - 1] == '\\') {
1732 // The backtick was preceded by a '\' character, remove the slash and
1733 // don't treat the backtick as the start of an expression.
1734 command.erase(start_backtick - 1, 1);
1735 // No need to add one to start_backtick since we just deleted a char.
1736 pos = start_backtick;
1737 continue;
1738 }
1739
1740 const size_t expr_content_start = start_backtick + 1;
1741 const size_t end_backtick = command.find('`', expr_content_start);
1742
1743 if (end_backtick == std::string::npos) {
1744 // Stop if there's no end backtick.
1745 break;
1746 }
1747
1748 if (end_backtick == expr_content_start) {
1749 // Skip over empty expression. (two backticks in a row)
1750 command.erase(start_backtick, 2);
1751 continue;
1752 }
1753
1754 std::string expr_str(command, expr_content_start,
1755 end_backtick - expr_content_start);
1756 error = PreprocessToken(expr_str);
1757 // We always stop at the first error:
1758 if (error.Fail())
1759 break;
1760
1761 command.erase(start_backtick, end_backtick - start_backtick + 1);
1762 command.insert(start_backtick, std::string(expr_str));
1763 pos = start_backtick + expr_str.size();
1764 }
1765 return error;
1766}
1767
1768Status
1770 Status error;
1772
1773 // Get a dummy target to allow for calculator mode while processing
1774 // backticks. This also helps break the infinite loop caused when target is
1775 // null.
1776 Target *exe_target = exe_ctx.GetTargetPtr();
1777 Target &target = exe_target ? *exe_target : m_debugger.GetDummyTarget();
1778
1779 ValueObjectSP expr_result_valobj_sp;
1780
1782 options.SetCoerceToId(false);
1783 options.SetUnwindOnError(true);
1784 options.SetIgnoreBreakpoints(true);
1785 options.SetKeepInMemory(false);
1786 options.SetTryAllThreads(true);
1787 options.SetTimeout(std::nullopt);
1788
1789 ExpressionResults expr_result =
1790 target.EvaluateExpression(expr_str.c_str(), exe_ctx.GetFramePtr(),
1791 expr_result_valobj_sp, options);
1792
1793 if (expr_result == eExpressionCompleted) {
1794 Scalar scalar;
1795 if (expr_result_valobj_sp)
1796 expr_result_valobj_sp =
1797 expr_result_valobj_sp->GetQualifiedRepresentationIfAvailable(
1798 expr_result_valobj_sp->GetDynamicValueType(), true);
1799 if (expr_result_valobj_sp->ResolveValue(scalar)) {
1800
1801 StreamString value_strm;
1802 const bool show_type = false;
1803 scalar.GetValue(value_strm, show_type);
1804 size_t value_string_size = value_strm.GetSize();
1805 if (value_string_size) {
1806 expr_str = value_strm.GetData();
1807 } else {
1808 error.SetErrorStringWithFormat("expression value didn't result "
1809 "in a scalar value for the "
1810 "expression '%s'",
1811 expr_str.c_str());
1812 }
1813 } else {
1814 error.SetErrorStringWithFormat("expression value didn't result "
1815 "in a scalar value for the "
1816 "expression '%s'",
1817 expr_str.c_str());
1818 }
1819 return error;
1820 }
1821
1822 // If we have an error from the expression evaluation it will be in the
1823 // ValueObject error, which won't be success and we will just report it.
1824 // But if for some reason we didn't get a value object at all, then we will
1825 // make up some helpful errors from the expression result.
1826 if (expr_result_valobj_sp)
1827 error = expr_result_valobj_sp->GetError();
1828
1829 if (error.Success()) {
1830 std::string result = lldb_private::toString(expr_result);
1831 error.SetErrorString(result + "for the expression '" + expr_str + "'");
1832 }
1833 return error;
1834}
1835
1836bool CommandInterpreter::HandleCommand(const char *command_line,
1837 LazyBool lazy_add_to_history,
1838 const ExecutionContext &override_context,
1839 CommandReturnObject &result) {
1840
1841 OverrideExecutionContext(override_context);
1842 bool status = HandleCommand(command_line, lazy_add_to_history, result);
1844 return status;
1845}
1846
1847bool CommandInterpreter::HandleCommand(const char *command_line,
1848 LazyBool lazy_add_to_history,
1849 CommandReturnObject &result,
1850 bool force_repeat_command) {
1851 std::string command_string(command_line);
1852 std::string original_command_string(command_line);
1853
1855 llvm::PrettyStackTraceFormat stack_trace("HandleCommand(command = \"%s\")",
1856 command_line);
1857
1858 LLDB_LOGF(log, "Processing command: %s", command_line);
1859 LLDB_SCOPED_TIMERF("Processing command: %s.", command_line);
1860
1861 if (INTERRUPT_REQUESTED(GetDebugger(), "Interrupted initiating command")) {
1862 result.AppendError("... Interrupted");
1863 return false;
1864 }
1865
1866 bool add_to_history;
1867 if (lazy_add_to_history == eLazyBoolCalculate)
1868 add_to_history = (m_command_source_depth == 0);
1869 else
1870 add_to_history = (lazy_add_to_history == eLazyBoolYes);
1871
1872 // The same `transcript_item` will be used below to add output and error of
1873 // the command.
1874 StructuredData::DictionarySP transcript_item;
1875 if (GetSaveTranscript()) {
1876 m_transcript_stream << "(lldb) " << command_line << '\n';
1877
1878 transcript_item = std::make_shared<StructuredData::Dictionary>();
1879 transcript_item->AddStringItem("command", command_line);
1880 transcript_item->AddIntegerItem(
1881 "timestampInEpochSeconds",
1882 std::chrono::duration_cast<std::chrono::seconds>(
1883 std::chrono::system_clock::now().time_since_epoch())
1884 .count());
1885 m_transcript.AddItem(transcript_item);
1886 }
1887
1888 bool empty_command = false;
1889 bool comment_command = false;
1890 if (command_string.empty())
1891 empty_command = true;
1892 else {
1893 const char *k_space_characters = "\t\n\v\f\r ";
1894
1895 size_t non_space = command_string.find_first_not_of(k_space_characters);
1896 // Check for empty line or comment line (lines whose first non-space
1897 // character is the comment character for this interpreter)
1898 if (non_space == std::string::npos)
1899 empty_command = true;
1900 else if (command_string[non_space] == m_comment_char)
1901 comment_command = true;
1902 else if (command_string[non_space] == CommandHistory::g_repeat_char) {
1903 llvm::StringRef search_str(command_string);
1904 search_str = search_str.drop_front(non_space);
1905 if (auto hist_str = m_command_history.FindString(search_str)) {
1906 add_to_history = false;
1907 command_string = std::string(*hist_str);
1908 original_command_string = std::string(*hist_str);
1909 } else {
1910 result.AppendErrorWithFormat("Could not find entry: %s in history",
1911 command_string.c_str());
1912 return false;
1913 }
1914 }
1915 }
1916
1917 if (empty_command) {
1918 if (!GetRepeatPreviousCommand()) {
1920 return true;
1921 }
1922
1923 if (m_command_history.IsEmpty()) {
1924 result.AppendError("empty command");
1925 return false;
1926 }
1927
1928 command_line = m_repeat_command.c_str();
1929 command_string = command_line;
1930 original_command_string = command_line;
1931 if (m_repeat_command.empty()) {
1932 result.AppendError("No auto repeat.");
1933 return false;
1934 }
1935
1936 add_to_history = false;
1937 } else if (comment_command) {
1939 return true;
1940 }
1941
1942 // Phase 1.
1943
1944 // Before we do ANY kind of argument processing, we need to figure out what
1945 // the real/final command object is for the specified command. This gets
1946 // complicated by the fact that the user could have specified an alias, and,
1947 // in translating the alias, there may also be command options and/or even
1948 // data (including raw text strings) that need to be found and inserted into
1949 // the command line as part of the translation. So this first step is plain
1950 // look-up and replacement, resulting in:
1951 // 1. the command object whose Execute method will actually be called
1952 // 2. a revised command string, with all substitutions and replacements
1953 // taken care of
1954 // From 1 above, we can determine whether the Execute function wants raw
1955 // input or not.
1956
1957 CommandObject *cmd_obj = ResolveCommandImpl(command_string, result);
1958
1959 // We have to preprocess the whole command string for Raw commands, since we
1960 // don't know the structure of the command. For parsed commands, we only
1961 // treat backticks as quote characters specially.
1962 // FIXME: We probably want to have raw commands do their own preprocessing.
1963 // For instance, I don't think people expect substitution in expr expressions.
1964 if (cmd_obj && cmd_obj->WantsRawCommandString()) {
1965 Status error(PreprocessCommand(command_string));
1966
1967 if (error.Fail()) {
1968 result.AppendError(error.AsCString());
1969 return false;
1970 }
1971 }
1972
1973 // Although the user may have abbreviated the command, the command_string now
1974 // has the command expanded to the full name. For example, if the input was
1975 // "br s -n main", command_string is now "breakpoint set -n main".
1976 if (log) {
1977 llvm::StringRef command_name = cmd_obj ? cmd_obj->GetCommandName() : "<not found>";
1978 LLDB_LOGF(log, "HandleCommand, cmd_obj : '%s'", command_name.str().c_str());
1979 LLDB_LOGF(log, "HandleCommand, (revised) command_string: '%s'",
1980 command_string.c_str());
1981 const bool wants_raw_input =
1982 (cmd_obj != nullptr) ? cmd_obj->WantsRawCommandString() : false;
1983 LLDB_LOGF(log, "HandleCommand, wants_raw_input:'%s'",
1984 wants_raw_input ? "True" : "False");
1985 }
1986
1987 // Phase 2.
1988 // Take care of things like setting up the history command & calling the
1989 // appropriate Execute method on the CommandObject, with the appropriate
1990 // arguments.
1991 StatsDuration execute_time;
1992 if (cmd_obj != nullptr) {
1993 bool generate_repeat_command = add_to_history;
1994 // If we got here when empty_command was true, then this command is a
1995 // stored "repeat command" which we should give a chance to produce it's
1996 // repeat command, even though we don't add repeat commands to the history.
1997 generate_repeat_command |= empty_command;
1998 // For `command regex`, the regex command (ex `bt`) is added to history, but
1999 // the resolved command (ex `thread backtrace`) is _not_ added to history.
2000 // However, the resolved command must be given the opportunity to provide a
2001 // repeat command. `force_repeat_command` supports this case.
2002 generate_repeat_command |= force_repeat_command;
2003 if (generate_repeat_command) {
2004 Args command_args(command_string);
2005 std::optional<std::string> repeat_command =
2006 cmd_obj->GetRepeatCommand(command_args, 0);
2007 if (repeat_command) {
2008 LLDB_LOGF(log, "Repeat command: %s", repeat_command->data());
2009 m_repeat_command.assign(*repeat_command);
2010 } else {
2011 m_repeat_command.assign(original_command_string);
2012 }
2013 }
2014
2015 if (add_to_history)
2016 m_command_history.AppendString(original_command_string);
2017
2018 std::string remainder;
2019 const std::size_t actual_cmd_name_len = cmd_obj->GetCommandName().size();
2020 if (actual_cmd_name_len < command_string.length())
2021 remainder = command_string.substr(actual_cmd_name_len);
2022
2023 // Remove any initial spaces
2024 size_t pos = remainder.find_first_not_of(k_white_space);
2025 if (pos != 0 && pos != std::string::npos)
2026 remainder.erase(0, pos);
2027
2028 LLDB_LOGF(
2029 log, "HandleCommand, command line after removing command name(s): '%s'",
2030 remainder.c_str());
2031
2032 // To test whether or not transcript should be saved, `transcript_item` is
2033 // used instead of `GetSaveTrasncript()`. This is because the latter will
2034 // fail when the command is "settings set interpreter.save-transcript true".
2035 if (transcript_item) {
2036 transcript_item->AddStringItem("commandName", cmd_obj->GetCommandName());
2037 transcript_item->AddStringItem("commandArguments", remainder);
2038 }
2039
2040 ElapsedTime elapsed(execute_time);
2041 cmd_obj->Execute(remainder.c_str(), result);
2042 }
2043
2044 LLDB_LOGF(log, "HandleCommand, command %s",
2045 (result.Succeeded() ? "succeeded" : "did not succeed"));
2046
2047 // To test whether or not transcript should be saved, `transcript_item` is
2048 // used instead of `GetSaveTrasncript()`. This is because the latter will
2049 // fail when the command is "settings set interpreter.save-transcript true".
2050 if (transcript_item) {
2053
2054 transcript_item->AddStringItem("output", result.GetOutputData());
2055 transcript_item->AddStringItem("error", result.GetErrorData());
2056 transcript_item->AddFloatItem("durationInSeconds",
2057 execute_time.get().count());
2058 }
2059
2060 return result.Succeeded();
2061}
2062
2064 bool look_for_subcommand = false;
2065
2066 // For any of the command completions a unique match will be a complete word.
2067
2068 if (request.GetParsedLine().GetArgumentCount() == 0) {
2069 // We got nothing on the command line, so return the list of commands
2070 bool include_aliases = true;
2071 StringList new_matches, descriptions;
2072 GetCommandNamesMatchingPartialString("", include_aliases, new_matches,
2073 descriptions);
2074 request.AddCompletions(new_matches, descriptions);
2075 } else if (request.GetCursorIndex() == 0) {
2076 // The cursor is in the first argument, so just do a lookup in the
2077 // dictionary.
2078 StringList new_matches, new_descriptions;
2079 CommandObject *cmd_obj =
2081 &new_matches, &new_descriptions);
2082
2083 if (new_matches.GetSize() && cmd_obj && cmd_obj->IsMultiwordObject() &&
2084 new_matches.GetStringAtIndex(0) != nullptr &&
2085 strcmp(request.GetParsedLine().GetArgumentAtIndex(0),
2086 new_matches.GetStringAtIndex(0)) == 0) {
2087 if (request.GetParsedLine().GetArgumentCount() != 1) {
2088 look_for_subcommand = true;
2089 new_matches.DeleteStringAtIndex(0);
2090 new_descriptions.DeleteStringAtIndex(0);
2091 request.AppendEmptyArgument();
2092 }
2093 }
2094 request.AddCompletions(new_matches, new_descriptions);
2095 }
2096
2097 if (request.GetCursorIndex() > 0 || look_for_subcommand) {
2098 // We are completing further on into a commands arguments, so find the
2099 // command and tell it to complete the command. First see if there is a
2100 // matching initial command:
2101 CommandObject *command_object =
2103 if (command_object) {
2104 request.ShiftArguments();
2105 command_object->HandleCompletion(request);
2106 }
2107 }
2108}
2109
2111
2112 // Don't complete comments, and if the line we are completing is just the
2113 // history repeat character, substitute the appropriate history line.
2114 llvm::StringRef first_arg = request.GetParsedLine().GetArgumentAtIndex(0);
2115
2116 if (!first_arg.empty()) {
2117 if (first_arg.front() == m_comment_char)
2118 return;
2119 if (first_arg.front() == CommandHistory::g_repeat_char) {
2120 if (auto hist_str = m_command_history.FindString(first_arg))
2121 request.AddCompletion(*hist_str, "Previous command history event",
2123 return;
2124 }
2125 }
2126
2127 HandleCompletionMatches(request);
2128}
2129
2130std::optional<std::string>
2132 if (line.empty())
2133 return std::nullopt;
2134 const size_t s = m_command_history.GetSize();
2135 for (int i = s - 1; i >= 0; --i) {
2136 llvm::StringRef entry = m_command_history.GetStringAtIndex(i);
2137 if (entry.consume_front(line))
2138 return entry.str();
2139 }
2140 return std::nullopt;
2141}
2142
2143void CommandInterpreter::UpdatePrompt(llvm::StringRef new_prompt) {
2144 EventSP prompt_change_event_sp(
2145 new Event(eBroadcastBitResetPrompt, new EventDataBytes(new_prompt)));
2146 ;
2147 BroadcastEvent(prompt_change_event_sp);
2149 m_command_io_handler_sp->SetPrompt(new_prompt);
2150}
2151
2152bool CommandInterpreter::Confirm(llvm::StringRef message, bool default_answer) {
2153 // Check AutoConfirm first:
2155 return default_answer;
2156
2157 IOHandlerConfirm *confirm =
2158 new IOHandlerConfirm(m_debugger, message, default_answer);
2159 IOHandlerSP io_handler_sp(confirm);
2160 m_debugger.RunIOHandlerSync(io_handler_sp);
2161 return confirm->GetResponse();
2162}
2163
2164const CommandAlias *
2165CommandInterpreter::GetAlias(llvm::StringRef alias_name) const {
2166 OptionArgVectorSP ret_val;
2167
2168 auto pos = m_alias_dict.find(std::string(alias_name));
2169 if (pos != m_alias_dict.end())
2170 return (CommandAlias *)pos->second.get();
2171
2172 return nullptr;
2173}
2174
2175bool CommandInterpreter::HasCommands() const { return (!m_command_dict.empty()); }
2176
2177bool CommandInterpreter::HasAliases() const { return (!m_alias_dict.empty()); }
2178
2179bool CommandInterpreter::HasUserCommands() const { return (!m_user_dict.empty()); }
2180
2182 return (!m_user_mw_dict.empty());
2183}
2184
2186
2188 const char *alias_name,
2189 Args &cmd_args,
2190 std::string &raw_input_string,
2191 CommandReturnObject &result) {
2192 OptionArgVectorSP option_arg_vector_sp =
2193 GetAlias(alias_name)->GetOptionArguments();
2194
2195 bool wants_raw_input = alias_cmd_obj->WantsRawCommandString();
2196
2197 // Make sure that the alias name is the 0th element in cmd_args
2198 std::string alias_name_str = alias_name;
2199 if (alias_name_str != cmd_args.GetArgumentAtIndex(0))
2200 cmd_args.Unshift(alias_name_str);
2201
2202 Args new_args(alias_cmd_obj->GetCommandName());
2203 if (new_args.GetArgumentCount() == 2)
2204 new_args.Shift();
2205
2206 if (option_arg_vector_sp.get()) {
2207 if (wants_raw_input) {
2208 // We have a command that both has command options and takes raw input.
2209 // Make *sure* it has a " -- " in the right place in the
2210 // raw_input_string.
2211 size_t pos = raw_input_string.find(" -- ");
2212 if (pos == std::string::npos) {
2213 // None found; assume it goes at the beginning of the raw input string
2214 raw_input_string.insert(0, " -- ");
2215 }
2216 }
2217
2218 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
2219 const size_t old_size = cmd_args.GetArgumentCount();
2220 std::vector<bool> used(old_size + 1, false);
2221
2222 used[0] = true;
2223
2224 int value_type;
2225 std::string option;
2226 std::string value;
2227 for (const auto &option_entry : *option_arg_vector) {
2228 std::tie(option, value_type, value) = option_entry;
2229 if (option == g_argument) {
2230 if (!wants_raw_input || (value != "--")) {
2231 // Since we inserted this above, make sure we don't insert it twice
2232 new_args.AppendArgument(value);
2233 }
2234 continue;
2235 }
2236
2237 if (value_type != OptionParser::eOptionalArgument)
2238 new_args.AppendArgument(option);
2239
2240 if (value == g_no_argument)
2241 continue;
2242
2243 int index = GetOptionArgumentPosition(value.c_str());
2244 if (index == 0) {
2245 // value was NOT a positional argument; must be a real value
2246 if (value_type != OptionParser::eOptionalArgument)
2247 new_args.AppendArgument(value);
2248 else {
2249 new_args.AppendArgument(option + value);
2250 }
2251
2252 } else if (static_cast<size_t>(index) >= cmd_args.GetArgumentCount()) {
2253 result.AppendErrorWithFormat("Not enough arguments provided; you "
2254 "need at least %d arguments to use "
2255 "this alias.\n",
2256 index);
2257 return;
2258 } else {
2259 // Find and remove cmd_args.GetArgumentAtIndex(i) from raw_input_string
2260 size_t strpos =
2261 raw_input_string.find(cmd_args.GetArgumentAtIndex(index));
2262 if (strpos != std::string::npos) {
2263 raw_input_string = raw_input_string.erase(
2264 strpos, strlen(cmd_args.GetArgumentAtIndex(index)));
2265 }
2266
2267 if (value_type != OptionParser::eOptionalArgument)
2268 new_args.AppendArgument(cmd_args.GetArgumentAtIndex(index));
2269 else {
2270 new_args.AppendArgument(option + cmd_args.GetArgumentAtIndex(index));
2271 }
2272 used[index] = true;
2273 }
2274 }
2275
2276 for (auto entry : llvm::enumerate(cmd_args.entries())) {
2277 if (!used[entry.index()] && !wants_raw_input)
2278 new_args.AppendArgument(entry.value().ref());
2279 }
2280
2281 cmd_args.Clear();
2282 cmd_args.SetArguments(new_args.GetArgumentCount(),
2283 new_args.GetConstArgumentVector());
2284 } else {
2286 // This alias was not created with any options; nothing further needs to be
2287 // done, unless it is a command that wants raw input, in which case we need
2288 // to clear the rest of the data from cmd_args, since its in the raw input
2289 // string.
2290 if (wants_raw_input) {
2291 cmd_args.Clear();
2292 cmd_args.SetArguments(new_args.GetArgumentCount(),
2293 new_args.GetConstArgumentVector());
2294 }
2295 return;
2296 }
2297
2299}
2300
2302 int position = 0; // Any string that isn't an argument position, i.e. '%'
2303 // followed by an integer, gets a position
2304 // of zero.
2305
2306 const char *cptr = in_string;
2307
2308 // Does it start with '%'
2309 if (cptr[0] == '%') {
2310 ++cptr;
2311
2312 // Is the rest of it entirely digits?
2313 if (isdigit(cptr[0])) {
2314 const char *start = cptr;
2315 while (isdigit(cptr[0]))
2316 ++cptr;
2317
2318 // We've gotten to the end of the digits; are we at the end of the
2319 // string?
2320 if (cptr[0] == '\0')
2321 position = atoi(start);
2322 }
2323 }
2324
2325 return position;
2326}
2327
2329 llvm::StringRef suffix = {}) {
2330 std::string init_file_name = ".lldbinit";
2331 if (!suffix.empty()) {
2332 init_file_name.append("-");
2333 init_file_name.append(suffix.str());
2334 }
2335
2337 llvm::sys::path::append(init_file, init_file_name);
2338
2339 FileSystem::Instance().Resolve(init_file);
2340}
2341
2343 LanguageType language) {
2344 if (language == eLanguageTypeUnknown) {
2346 if (auto main_repl_language = repl_languages.GetSingularLanguage())
2347 language = *main_repl_language;
2348 else
2349 return;
2350 }
2351
2352 std::string init_file_name =
2353 (llvm::Twine(".lldbinit-") +
2354 llvm::Twine(Language::GetNameForLanguageType(language)) +
2355 llvm::Twine("-repl"))
2356 .str();
2358 llvm::sys::path::append(init_file, init_file_name);
2359 FileSystem::Instance().Resolve(init_file);
2360}
2361
2363 llvm::StringRef s = ".lldbinit";
2364 init_file.assign(s.begin(), s.end());
2365 FileSystem::Instance().Resolve(init_file);
2366}
2367
2369 CommandReturnObject &result) {
2370 assert(!m_skip_lldbinit_files);
2371
2372 if (!FileSystem::Instance().Exists(file)) {
2374 return;
2375 }
2376
2377 // Use HandleCommand to 'source' the given file; this will do the actual
2378 // broadcasting of the commands back to any appropriate listener (see
2379 // CommandObjectSource::Execute for more details).
2380 const bool saved_batch = SetBatchCommandMode(true);
2382 options.SetSilent(true);
2383 options.SetPrintErrors(true);
2384 options.SetStopOnError(false);
2385 options.SetStopOnContinue(true);
2386 HandleCommandsFromFile(file, options, result);
2387 SetBatchCommandMode(saved_batch);
2388}
2389
2393 return;
2394 }
2395
2396 llvm::SmallString<128> init_file;
2397 GetCwdInitFile(init_file);
2398 if (!FileSystem::Instance().Exists(init_file)) {
2400 return;
2401 }
2402
2403 LoadCWDlldbinitFile should_load =
2405
2406 switch (should_load) {
2409 break;
2411 SourceInitFile(FileSpec(init_file.str()), result);
2412 break;
2413 case eLoadCWDlldbinitWarn: {
2414 llvm::SmallString<128> home_init_file;
2415 GetHomeInitFile(home_init_file);
2416 if (llvm::sys::path::parent_path(init_file) ==
2417 llvm::sys::path::parent_path(home_init_file)) {
2419 } else {
2421 }
2422 }
2423 }
2424}
2425
2426/// We will first see if there is an application specific ".lldbinit" file
2427/// whose name is "~/.lldbinit" followed by a "-" and the name of the program.
2428/// If this file doesn't exist, we fall back to the REPL init file or the
2429/// default home init file in "~/.lldbinit".
2431 bool is_repl) {
2434 return;
2435 }
2436
2437 llvm::SmallString<128> init_file;
2438
2439 if (is_repl)
2440 GetHomeREPLInitFile(init_file, GetDebugger().GetREPLLanguage());
2441
2442 if (init_file.empty())
2443 GetHomeInitFile(init_file);
2444
2445 if (!m_skip_app_init_files) {
2446 llvm::StringRef program_name =
2447 HostInfo::GetProgramFileSpec().GetFilename().GetStringRef();
2448 llvm::SmallString<128> program_init_file;
2449 GetHomeInitFile(program_init_file, program_name);
2450 if (FileSystem::Instance().Exists(program_init_file))
2451 init_file = program_init_file;
2452 }
2453
2454 SourceInitFile(FileSpec(init_file.str()), result);
2455}
2456
2458#ifdef LLDB_GLOBAL_INIT_DIRECTORY
2459 if (!m_skip_lldbinit_files) {
2460 FileSpec init_file(LLDB_GLOBAL_INIT_DIRECTORY);
2461 if (init_file)
2462 init_file.MakeAbsolute(HostInfo::GetShlibDir());
2463
2464 init_file.AppendPathComponent("lldbinit");
2465 SourceInitFile(init_file, result);
2466 return;
2467 }
2468#endif
2470}
2471
2473 const char *prefix = GetDebugger().GetIOHandlerCommandPrefix();
2474 return prefix == nullptr ? "" : prefix;
2475}
2476
2477PlatformSP CommandInterpreter::GetPlatform(bool prefer_target_platform) {
2478 PlatformSP platform_sp;
2479 if (prefer_target_platform) {
2481 Target *target = exe_ctx.GetTargetPtr();
2482 if (target)
2483 platform_sp = target->GetPlatform();
2484 }
2485
2486 if (!platform_sp)
2488 return platform_sp;
2489}
2490
2492 auto exe_ctx = GetExecutionContext();
2493 TargetSP target_sp = exe_ctx.GetTargetSP();
2494 if (!target_sp)
2495 return false;
2496
2497 ProcessSP process_sp(target_sp->GetProcessSP());
2498 if (!process_sp)
2499 return false;
2500
2501 if (eStateStopped != process_sp->GetState())
2502 return false;
2503
2504 for (const auto &thread_sp : process_sp->GetThreadList().Threads()) {
2505 StopInfoSP stop_info = thread_sp->GetStopInfo();
2506 if (!stop_info) {
2507 // If there's no stop_info, keep iterating through the other threads;
2508 // it's enough that any thread has got a stop_info that indicates
2509 // an abnormal stop, to consider the process to be stopped abnormally.
2510 continue;
2511 }
2512
2513 const StopReason reason = stop_info->GetStopReason();
2514 if (reason == eStopReasonException ||
2515 reason == eStopReasonInstrumentation ||
2516 reason == eStopReasonProcessorTrace)
2517 return true;
2518
2519 if (reason == eStopReasonSignal) {
2520 const auto stop_signal = static_cast<int32_t>(stop_info->GetValue());
2521 UnixSignalsSP signals_sp = process_sp->GetUnixSignals();
2522 if (!signals_sp || !signals_sp->SignalIsValid(stop_signal))
2523 // The signal is unknown, treat it as abnormal.
2524 return true;
2525
2526 const auto sigint_num = signals_sp->GetSignalNumberFromName("SIGINT");
2527 const auto sigstop_num = signals_sp->GetSignalNumberFromName("SIGSTOP");
2528 if ((stop_signal != sigint_num) && (stop_signal != sigstop_num))
2529 // The signal very likely implies a crash.
2530 return true;
2531 }
2532 }
2533
2534 return false;
2535}
2536
2537void
2539 const ExecutionContext &override_context,
2540 const CommandInterpreterRunOptions &options,
2541 CommandReturnObject &result) {
2542
2543 OverrideExecutionContext(override_context);
2544 HandleCommands(commands, options, result);
2546}
2547
2549 const CommandInterpreterRunOptions &options,
2550 CommandReturnObject &result) {
2551 size_t num_lines = commands.GetSize();
2552
2553 // If we are going to continue past a "continue" then we need to run the
2554 // commands synchronously. Make sure you reset this value anywhere you return
2555 // from the function.
2556
2557 bool old_async_execution = m_debugger.GetAsyncExecution();
2558
2559 if (!options.GetStopOnContinue()) {
2561 }
2562
2563 for (size_t idx = 0; idx < num_lines; idx++) {
2564 const char *cmd = commands.GetStringAtIndex(idx);
2565 if (cmd[0] == '\0')
2566 continue;
2567
2568 if (options.GetEchoCommands()) {
2569 // TODO: Add Stream support.
2570 result.AppendMessageWithFormat("%s %s\n",
2571 m_debugger.GetPrompt().str().c_str(), cmd);
2572 }
2573
2575 tmp_result.SetInteractive(result.GetInteractive());
2576 tmp_result.SetSuppressImmediateOutput(true);
2577
2578 // We might call into a regex or alias command, in which case the
2579 // add_to_history will get lost. This m_command_source_depth dingus is the
2580 // way we turn off adding to the history in that case, so set it up here.
2581 if (!options.GetAddToHistory())
2583 bool success = HandleCommand(cmd, options.m_add_to_history, tmp_result);
2584 if (!options.GetAddToHistory())
2586
2587 if (options.GetPrintResults()) {
2588 if (tmp_result.Succeeded())
2589 result.AppendMessage(tmp_result.GetOutputData());
2590 }
2591
2592 if (!success || !tmp_result.Succeeded()) {
2593 llvm::StringRef error_msg = tmp_result.GetErrorData();
2594 if (error_msg.empty())
2595 error_msg = "<unknown error>.\n";
2596 if (options.GetStopOnError()) {
2597 result.AppendErrorWithFormat(
2598 "Aborting reading of commands after command #%" PRIu64
2599 ": '%s' failed with %s",
2600 (uint64_t)idx, cmd, error_msg.str().c_str());
2601 m_debugger.SetAsyncExecution(old_async_execution);
2602 return;
2603 } else if (options.GetPrintResults()) {
2605 "Command #%" PRIu64 " '%s' failed with %s", (uint64_t)idx + 1, cmd,
2606 error_msg.str().c_str());
2607 }
2608 }
2609
2610 if (result.GetImmediateOutputStream())
2611 result.GetImmediateOutputStream()->Flush();
2612
2613 if (result.GetImmediateErrorStream())
2614 result.GetImmediateErrorStream()->Flush();
2615
2616 // N.B. Can't depend on DidChangeProcessState, because the state coming
2617 // into the command execution could be running (for instance in Breakpoint
2618 // Commands. So we check the return value to see if it is has running in
2619 // it.
2620 if ((tmp_result.GetStatus() == eReturnStatusSuccessContinuingNoResult) ||
2622 if (options.GetStopOnContinue()) {
2623 // If we caused the target to proceed, and we're going to stop in that
2624 // case, set the status in our real result before returning. This is
2625 // an error if the continue was not the last command in the set of
2626 // commands to be run.
2627 if (idx != num_lines - 1)
2628 result.AppendErrorWithFormat(
2629 "Aborting reading of commands after command #%" PRIu64
2630 ": '%s' continued the target.\n",
2631 (uint64_t)idx + 1, cmd);
2632 else
2633 result.AppendMessageWithFormat("Command #%" PRIu64
2634 " '%s' continued the target.\n",
2635 (uint64_t)idx + 1, cmd);
2636
2637 result.SetStatus(tmp_result.GetStatus());
2638 m_debugger.SetAsyncExecution(old_async_execution);
2639
2640 return;
2641 }
2642 }
2643
2644 // Also check for "stop on crash here:
2645 if (tmp_result.GetDidChangeProcessState() && options.GetStopOnCrash() &&
2647 if (idx != num_lines - 1)
2648 result.AppendErrorWithFormat(
2649 "Aborting reading of commands after command #%" PRIu64
2650 ": '%s' stopped with a signal or exception.\n",
2651 (uint64_t)idx + 1, cmd);
2652 else
2654 "Command #%" PRIu64 " '%s' stopped with a signal or exception.\n",
2655 (uint64_t)idx + 1, cmd);
2656
2657 result.SetStatus(tmp_result.GetStatus());
2658 m_debugger.SetAsyncExecution(old_async_execution);
2659
2660 return;
2661 }
2662 }
2663
2665 m_debugger.SetAsyncExecution(old_async_execution);
2666}
2667
2668// Make flags that we can pass into the IOHandler so our delegates can do the
2669// right thing
2670enum {
2680
2682 FileSpec &cmd_file, const ExecutionContext &context,
2683 const CommandInterpreterRunOptions &options, CommandReturnObject &result) {
2684 OverrideExecutionContext(context);
2685 HandleCommandsFromFile(cmd_file, options, result);
2687}
2688
2690 const CommandInterpreterRunOptions &options, CommandReturnObject &result) {
2691 if (!FileSystem::Instance().Exists(cmd_file)) {
2692 result.AppendErrorWithFormat(
2693 "Error reading commands from file %s - file not found.\n",
2694 cmd_file.GetFilename().AsCString("<Unknown>"));
2695 return;
2696 }
2697
2698 std::string cmd_file_path = cmd_file.GetPath();
2699 auto input_file_up =
2701 if (!input_file_up) {
2702 std::string error = llvm::toString(input_file_up.takeError());
2704 "error: an error occurred read file '{0}': {1}\n", cmd_file_path,
2705 llvm::fmt_consume(input_file_up.takeError()));
2706 return;
2707 }
2708 FileSP input_file_sp = FileSP(std::move(input_file_up.get()));
2709
2710 Debugger &debugger = GetDebugger();
2711
2712 uint32_t flags = 0;
2713
2714 if (options.m_stop_on_continue == eLazyBoolCalculate) {
2715 if (m_command_source_flags.empty()) {
2716 // Stop on continue by default
2718 } else if (m_command_source_flags.back() &
2721 }
2722 } else if (options.m_stop_on_continue == eLazyBoolYes) {
2724 }
2725
2726 if (options.m_stop_on_error == eLazyBoolCalculate) {
2727 if (m_command_source_flags.empty()) {
2732 }
2733 } else if (options.m_stop_on_error == eLazyBoolYes) {
2735 }
2736
2737 // stop-on-crash can only be set, if it is present in all levels of
2738 // pushed flag sets.
2739 if (options.GetStopOnCrash()) {
2740 if (m_command_source_flags.empty()) {
2744 }
2745 }
2746
2747 if (options.m_echo_commands == eLazyBoolCalculate) {
2748 if (m_command_source_flags.empty()) {
2749 // Echo command by default
2753 }
2754 } else if (options.m_echo_commands == eLazyBoolYes) {
2756 }
2757
2758 // We will only ever ask for this flag, if we echo commands in general.
2760 if (m_command_source_flags.empty()) {
2761 // Echo comments by default
2763 } else if (m_command_source_flags.back() &
2766 }
2767 } else if (options.m_echo_comment_commands == eLazyBoolYes) {
2769 }
2770
2771 if (options.m_print_results == eLazyBoolCalculate) {
2772 if (m_command_source_flags.empty()) {
2773 // Print output by default
2777 }
2778 } else if (options.m_print_results == eLazyBoolYes) {
2780 }
2781
2782 if (options.m_print_errors == eLazyBoolCalculate) {
2783 if (m_command_source_flags.empty()) {
2784 // Print output by default
2788 }
2789 } else if (options.m_print_errors == eLazyBoolYes) {
2791 }
2792
2793 if (flags & eHandleCommandFlagPrintResult) {
2794 debugger.GetOutputFile().Printf("Executing commands in '%s'.\n",
2795 cmd_file_path.c_str());
2796 }
2797
2798 // Used for inheriting the right settings when "command source" might
2799 // have nested "command source" commands
2800 lldb::StreamFileSP empty_stream_sp;
2801 m_command_source_flags.push_back(flags);
2802 IOHandlerSP io_handler_sp(new IOHandlerEditline(
2803 debugger, IOHandler::Type::CommandInterpreter, input_file_sp,
2804 empty_stream_sp, // Pass in an empty stream so we inherit the top
2805 // input reader output stream
2806 empty_stream_sp, // Pass in an empty stream so we inherit the top
2807 // input reader error stream
2808 flags,
2809 nullptr, // Pass in NULL for "editline_name" so no history is saved,
2810 // or written
2811 debugger.GetPrompt(), llvm::StringRef(),
2812 false, // Not multi-line
2813 debugger.GetUseColor(), 0, *this));
2814 const bool old_async_execution = debugger.GetAsyncExecution();
2815
2816 // Set synchronous execution if we are not stopping on continue
2817 if ((flags & eHandleCommandFlagStopOnContinue) == 0)
2818 debugger.SetAsyncExecution(false);
2819
2822
2823 debugger.RunIOHandlerSync(io_handler_sp);
2824 if (!m_command_source_flags.empty())
2825 m_command_source_flags.pop_back();
2826
2827 m_command_source_dirs.pop_back();
2829
2831 debugger.SetAsyncExecution(old_async_execution);
2832}
2833
2835
2838}
2839
2841 llvm::StringRef prefix,
2842 llvm::StringRef help_text) {
2843 const uint32_t max_columns = m_debugger.GetTerminalWidth();
2844
2845 size_t line_width_max = max_columns - prefix.size();
2846 if (line_width_max < 16)
2847 line_width_max = help_text.size() + prefix.size();
2848
2849 strm.IndentMore(prefix.size());
2850 bool prefixed_yet = false;
2851 // Even if we have no help text we still want to emit the command name.
2852 if (help_text.empty())
2853 help_text = "No help text";
2854 while (!help_text.empty()) {
2855 // Prefix the first line, indent subsequent lines to line up
2856 if (!prefixed_yet) {
2857 strm << prefix;
2858 prefixed_yet = true;
2859 } else
2860 strm.Indent();
2861
2862 // Never print more than the maximum on one line.
2863 llvm::StringRef this_line = help_text.substr(0, line_width_max);
2864
2865 // Always break on an explicit newline.
2866 std::size_t first_newline = this_line.find_first_of("\n");
2867
2868 // Don't break on space/tab unless the text is too long to fit on one line.
2869 std::size_t last_space = llvm::StringRef::npos;
2870 if (this_line.size() != help_text.size())
2871 last_space = this_line.find_last_of(" \t");
2872
2873 // Break at whichever condition triggered first.
2874 this_line = this_line.substr(0, std::min(first_newline, last_space));
2875 strm.PutCString(this_line);
2876 strm.EOL();
2877
2878 // Remove whitespace / newlines after breaking.
2879 help_text = help_text.drop_front(this_line.size()).ltrim();
2880 }
2881 strm.IndentLess(prefix.size());
2882}
2883
2885 llvm::StringRef word_text,
2886 llvm::StringRef separator,
2887 llvm::StringRef help_text,
2888 size_t max_word_len) {
2889 StreamString prefix_stream;
2890 prefix_stream.Printf(" %-*s %*s ", (int)max_word_len, word_text.data(),
2891 (int)separator.size(), separator.data());
2892 OutputFormattedHelpText(strm, prefix_stream.GetString(), help_text);
2893}
2894
2895void CommandInterpreter::OutputHelpText(Stream &strm, llvm::StringRef word_text,
2896 llvm::StringRef separator,
2897 llvm::StringRef help_text,
2898 uint32_t max_word_len) {
2899 int indent_size = max_word_len + separator.size() + 2;
2900
2901 strm.IndentMore(indent_size);
2902
2903 StreamString text_strm;
2904 text_strm.Printf("%-*s ", (int)max_word_len, word_text.data());
2905 text_strm << separator << " " << help_text;
2906
2907 const uint32_t max_columns = m_debugger.GetTerminalWidth();
2908
2909 llvm::StringRef text = text_strm.GetString();
2910
2911 uint32_t chars_left = max_columns;
2912
2913 auto nextWordLength = [](llvm::StringRef S) {
2914 size_t pos = S.find(' ');
2915 return pos == llvm::StringRef::npos ? S.size() : pos;
2916 };
2917
2918 while (!text.empty()) {
2919 if (text.front() == '\n' ||
2920 (text.front() == ' ' && nextWordLength(text.ltrim(' ')) > chars_left)) {
2921 strm.EOL();
2922 strm.Indent();
2923 chars_left = max_columns - indent_size;
2924 if (text.front() == '\n')
2925 text = text.drop_front();
2926 else
2927 text = text.ltrim(' ');
2928 } else {
2929 strm.PutChar(text.front());
2930 --chars_left;
2931 text = text.drop_front();
2932 }
2933 }
2934
2935 strm.EOL();
2936 strm.IndentLess(indent_size);
2937}
2938
2940 llvm::StringRef search_word, StringList &commands_found,
2941 StringList &commands_help, const CommandObject::CommandMap &command_map) {
2942 for (const auto &pair : command_map) {
2943 llvm::StringRef command_name = pair.first;
2944 CommandObject *cmd_obj = pair.second.get();
2945
2946 const bool search_short_help = true;
2947 const bool search_long_help = false;
2948 const bool search_syntax = false;
2949 const bool search_options = false;
2950 if (command_name.contains_insensitive(search_word) ||
2951 cmd_obj->HelpTextContainsWord(search_word, search_short_help,
2952 search_long_help, search_syntax,
2953 search_options)) {
2954 commands_found.AppendString(command_name);
2955 commands_help.AppendString(cmd_obj->GetHelp());
2956 }
2957
2958 if (auto *multiword_cmd = cmd_obj->GetAsMultiwordCommand()) {
2959 StringList subcommands_found;
2960 FindCommandsForApropos(search_word, subcommands_found, commands_help,
2961 multiword_cmd->GetSubcommandDictionary());
2962 for (const auto &subcommand_name : subcommands_found) {
2963 std::string qualified_name =
2964 (command_name + " " + subcommand_name).str();
2965 commands_found.AppendString(qualified_name);
2966 }
2967 }
2968 }
2969}
2970
2971void CommandInterpreter::FindCommandsForApropos(llvm::StringRef search_word,
2972 StringList &commands_found,
2973 StringList &commands_help,
2974 bool search_builtin_commands,
2975 bool search_user_commands,
2976 bool search_alias_commands,
2977 bool search_user_mw_commands) {
2978 CommandObject::CommandMap::const_iterator pos;
2979
2980 if (search_builtin_commands)
2981 FindCommandsForApropos(search_word, commands_found, commands_help,
2983
2984 if (search_user_commands)
2985 FindCommandsForApropos(search_word, commands_found, commands_help,
2986 m_user_dict);
2987
2988 if (search_user_mw_commands)
2989 FindCommandsForApropos(search_word, commands_found, commands_help,
2991
2992 if (search_alias_commands)
2993 FindCommandsForApropos(search_word, commands_found, commands_help,
2994 m_alias_dict);
2995}
2996
2998 return !m_overriden_exe_contexts.empty()
3001}
3002
3004 const ExecutionContext &override_context) {
3005 m_overriden_exe_contexts.push(override_context);
3006}
3007
3009 if (!m_overriden_exe_contexts.empty())
3011}
3012
3014 if (ProcessSP process_sp = GetExecutionContext().GetProcessSP())
3015 m_debugger.FlushProcessOutput(*process_sp, /*flush_stdout*/ true,
3016 /*flush_stderr*/ true);
3017}
3018
3020 auto idle_state = CommandHandlingState::eIdle;
3021 if (m_command_state.compare_exchange_strong(
3024 else
3027}
3028
3031 if (--m_iohandler_nesting_level == 0) {
3032 auto prev_state = m_command_state.exchange(CommandHandlingState::eIdle);
3034 }
3035}
3036
3038 auto in_progress = CommandHandlingState::eInProgress;
3039 return m_command_state.compare_exchange_strong(
3041}
3042
3045 return false;
3046
3047 bool was_interrupted =
3049 lldbassert(!was_interrupted || m_iohandler_nesting_level > 0);
3050 return was_interrupted;
3051}
3052
3054 llvm::StringRef str,
3055 bool is_stdout) {
3056
3057 lldb::StreamFileSP stream = is_stdout ? io_handler.GetOutputStreamFileSP()
3058 : io_handler.GetErrorStreamFileSP();
3059 // Split the output into lines and poll for interrupt requests
3060 bool had_output = !str.empty();
3061 while (!str.empty()) {
3062 llvm::StringRef line;
3063 std::tie(line, str) = str.split('\n');
3064 {
3065 std::lock_guard<std::recursive_mutex> guard(io_handler.GetOutputMutex());
3066 stream->Write(line.data(), line.size());
3067 stream->Write("\n", 1);
3068 }
3069 }
3070
3071 std::lock_guard<std::recursive_mutex> guard(io_handler.GetOutputMutex());
3072 if (had_output &&
3073 INTERRUPT_REQUESTED(GetDebugger(), "Interrupted dumping command output"))
3074 stream->Printf("\n... Interrupted.\n");
3075 stream->Flush();
3076}
3077
3079 llvm::StringRef line, const Flags &io_handler_flags) const {
3080 if (!io_handler_flags.Test(eHandleCommandFlagEchoCommand))
3081 return false;
3082
3083 llvm::StringRef command = line.trim();
3084 if (command.empty())
3085 return true;
3086
3087 if (command.front() == m_comment_char)
3088 return io_handler_flags.Test(eHandleCommandFlagEchoCommentCommand);
3089
3090 return true;
3091}
3092
3094 std::string &line) {
3095 // If we were interrupted, bail out...
3096 if (WasInterrupted())
3097 return;
3098
3099 const bool is_interactive = io_handler.GetIsInteractive();
3100 const bool allow_repeats =
3102
3103 if (!is_interactive && !allow_repeats) {
3104 // When we are not interactive, don't execute blank lines. This will happen
3105 // sourcing a commands file. We don't want blank lines to repeat the
3106 // previous command and cause any errors to occur (like redefining an
3107 // alias, get an error and stop parsing the commands file).
3108 // But obey the AllowRepeats flag if the user has set it.
3109 if (line.empty())
3110 return;
3111 }
3112 if (!is_interactive) {
3113 // When using a non-interactive file handle (like when sourcing commands
3114 // from a file) we need to echo the command out so we don't just see the
3115 // command output and no command...
3116 if (EchoCommandNonInteractive(line, io_handler.GetFlags())) {
3117 std::lock_guard<std::recursive_mutex> guard(io_handler.GetOutputMutex());
3118 io_handler.GetOutputStreamFileSP()->Printf(
3119 "%s%s\n", io_handler.GetPrompt(), line.c_str());
3120 }
3121 }
3122
3124
3126 bool pushed_exe_ctx = false;
3127 if (exe_ctx.HasTargetScope()) {
3128 OverrideExecutionContext(exe_ctx);
3129 pushed_exe_ctx = true;
3130 }
3131 auto finalize = llvm::make_scope_exit([this, pushed_exe_ctx]() {
3132 if (pushed_exe_ctx)
3134 });
3135
3137 HandleCommand(line.c_str(), eLazyBoolCalculate, result);
3138
3139 // Now emit the command output text from the command we just executed
3140 if ((result.Succeeded() &&
3143 // Display any STDOUT/STDERR _prior_ to emitting the command result text
3145
3146 if (!result.GetImmediateOutputStream()) {
3147 llvm::StringRef output = result.GetOutputData();
3148 PrintCommandOutput(io_handler, output, true);
3149 }
3150
3151 // Now emit the command error text from the command we just executed
3152 if (!result.GetImmediateErrorStream()) {
3153 llvm::StringRef error = result.GetErrorData();
3154 PrintCommandOutput(io_handler, error, false);
3155 }
3156 }
3157
3159
3160 switch (result.GetStatus()) {
3165 break;
3166
3170 io_handler.SetIsDone(true);
3171 break;
3172
3175 if (io_handler.GetFlags().Test(eHandleCommandFlagStopOnError)) {
3177 io_handler.SetIsDone(true);
3178 }
3179 break;
3180
3181 case eReturnStatusQuit:
3183 io_handler.SetIsDone(true);
3184 break;
3185 }
3186
3187 // Finally, if we're going to stop on crash, check that here:
3189 result.GetDidChangeProcessState() &&
3192 io_handler.SetIsDone(true);
3194 }
3195}
3196
3199 Process *process = exe_ctx.GetProcessPtr();
3200
3201 if (InterruptCommand())
3202 return true;
3203
3204 if (process) {
3205 StateType state = process->GetState();
3206 if (StateIsRunningState(state)) {
3207 process->Halt();
3208 return true; // Don't do any updating when we are running
3209 }
3210 }
3211
3212 ScriptInterpreter *script_interpreter =
3214 if (script_interpreter) {
3215 if (script_interpreter->Interrupt())
3216 return true;
3217 }
3218 return false;
3219}
3220
3222 CommandReturnObject &result, std::optional<std::string> output_file) {
3223 if (output_file == std::nullopt || output_file->empty()) {
3224 std::string now = llvm::to_string(std::chrono::system_clock::now());
3225 std::replace(now.begin(), now.end(), ' ', '_');
3226 // Can't have file name with colons on Windows
3227 std::replace(now.begin(), now.end(), ':', '-');
3228 const std::string file_name = "lldb_session_" + now + ".log";
3229
3230 FileSpec save_location = GetSaveSessionDirectory();
3231
3232 if (!save_location)
3233 save_location = HostInfo::GetGlobalTempDir();
3234
3235 FileSystem::Instance().Resolve(save_location);
3236 save_location.AppendPathComponent(file_name);
3237 output_file = save_location.GetPath();
3238 }
3239
3240 auto error_out = [&](llvm::StringRef error_message, std::string description) {
3241 LLDB_LOG(GetLog(LLDBLog::Commands), "{0} ({1}:{2})", error_message,
3242 output_file, description);
3244 "Failed to save session's transcripts to {0}!", *output_file);
3245 return false;
3246 };
3247
3251
3252 auto opened_file = FileSystem::Instance().Open(FileSpec(*output_file), flags);
3253
3254 if (!opened_file)
3255 return error_out("Unable to create file",
3256 llvm::toString(opened_file.takeError()));
3257
3258 FileUP file = std::move(opened_file.get());
3259
3260 size_t byte_size = m_transcript_stream.GetSize();
3261
3262 Status error = file->Write(m_transcript_stream.GetData(), byte_size);
3263
3264 if (error.Fail() || byte_size != m_transcript_stream.GetSize())
3265 return error_out("Unable to write to destination file",
3266 "Bytes written do not match transcript size.");
3267
3269 result.AppendMessageWithFormat("Session's transcripts saved to %s\n",
3270 output_file->c_str());
3271
3273 const FileSpec file_spec;
3274 error = file->GetFileSpec(const_cast<FileSpec &>(file_spec));
3275 if (error.Success()) {
3276 if (llvm::Error e = Host::OpenFileInExternalEditor(
3277 m_debugger.GetExternalEditor(), file_spec, 1))
3278 result.AppendError(llvm::toString(std::move(e)));
3279 }
3280 }
3281
3282 return true;
3283}
3284
3286 return (GetIOHandler() ? GetIOHandler()->GetIsInteractive() : false);
3287}
3288
3290 if (m_command_source_dirs.empty())
3291 return {};
3292 return m_command_source_dirs.back();
3293}
3294
3296 const char *prompt, IOHandlerDelegate &delegate, void *baton) {
3297 Debugger &debugger = GetDebugger();
3298 IOHandlerSP io_handler_sp(
3300 "lldb", // Name of input reader for history
3301 llvm::StringRef(prompt), // Prompt
3302 llvm::StringRef(), // Continuation prompt
3303 true, // Get multiple lines
3304 debugger.GetUseColor(),
3305 0, // Don't show line numbers
3306 delegate)); // IOHandlerDelegate
3307
3308 if (io_handler_sp) {
3309 io_handler_sp->SetUserData(baton);
3310 debugger.RunIOHandlerAsync(io_handler_sp);
3311 }
3312}
3313
3315 const char *prompt, IOHandlerDelegate &delegate, void *baton) {
3316 Debugger &debugger = GetDebugger();
3317 IOHandlerSP io_handler_sp(
3319 "lldb-python", // Name of input reader for history
3320 llvm::StringRef(prompt), // Prompt
3321 llvm::StringRef(), // Continuation prompt
3322 true, // Get multiple lines
3323 debugger.GetUseColor(),
3324 0, // Don't show line numbers
3325 delegate)); // IOHandlerDelegate
3326
3327 if (io_handler_sp) {
3328 io_handler_sp->SetUserData(baton);
3329 debugger.RunIOHandlerAsync(io_handler_sp);
3330 }
3331}
3332
3335}
3336
3340 // Always re-create the IOHandlerEditline in case the input changed. The old
3341 // instance might have had a non-interactive input and now it does or vice
3342 // versa.
3343 if (force_create || !m_command_io_handler_sp) {
3344 // Always re-create the IOHandlerEditline in case the input changed. The
3345 // old instance might have had a non-interactive input and now it does or
3346 // vice versa.
3347 uint32_t flags = 0;
3348
3349 if (options) {
3350 if (options->m_stop_on_continue == eLazyBoolYes)
3352 if (options->m_stop_on_error == eLazyBoolYes)
3354 if (options->m_stop_on_crash == eLazyBoolYes)
3356 if (options->m_echo_commands != eLazyBoolNo)
3358 if (options->m_echo_comment_commands != eLazyBoolNo)
3360 if (options->m_print_results != eLazyBoolNo)
3362 if (options->m_print_errors != eLazyBoolNo)
3364 if (options->m_allow_repeats == eLazyBoolYes)
3366 } else {
3369 }
3370
3371 m_command_io_handler_sp = std::make_shared<IOHandlerEditline>(
3374 m_debugger.GetErrorStreamSP(), flags, "lldb", m_debugger.GetPrompt(),
3375 llvm::StringRef(), // Continuation prompt
3376 false, // Don't enable multiple line input, just single line commands
3378 0, // Don't show line numbers
3379 *this); // IOHandlerDelegate
3380 }
3382}
3383
3386 // Always re-create the command interpreter when we run it in case any file
3387 // handles have changed.
3388 bool force_create = true;
3389 m_debugger.RunIOHandlerAsync(GetIOHandler(force_create, &options));
3391
3392 if (options.GetAutoHandleEvents())
3394
3395 if (options.GetSpawnThread()) {
3397 } else {
3398 // If the current thread is not managed by a host thread, we won't detect
3399 // that this IS the CommandInterpreter IOHandler thread, so make it so:
3400 HostThread new_io_handler_thread(Host::GetCurrentThread());
3401 HostThread old_io_handler_thread =
3402 m_debugger.SetIOHandlerThread(new_io_handler_thread);
3404 m_debugger.SetIOHandlerThread(old_io_handler_thread);
3405
3406 if (options.GetAutoHandleEvents())
3408 }
3409
3410 return m_result;
3411}
3412
3415 CommandReturnObject &result) {
3416 std::string scratch_command(command_line); // working copy so we don't modify
3417 // command_line unless we succeed
3418 CommandObject *cmd_obj = nullptr;
3419 StreamString revised_command_line;
3420 bool wants_raw_input = false;
3421 std::string next_word;
3422 StringList matches;
3423 bool done = false;
3424 while (!done) {
3425 char quote_char = '\0';
3426 std::string suffix;
3427 ExtractCommand(scratch_command, next_word, suffix, quote_char);
3428 if (cmd_obj == nullptr) {
3429 std::string full_name;
3430 bool is_alias = GetAliasFullName(next_word, full_name);
3431 cmd_obj = GetCommandObject(next_word, &matches);
3432 bool is_real_command =
3433 (!is_alias) || (cmd_obj != nullptr && !cmd_obj->IsAlias());
3434 if (!is_real_command) {
3435 matches.Clear();
3436 std::string alias_result;
3437 cmd_obj =
3438 BuildAliasResult(full_name, scratch_command, alias_result, result);
3439 revised_command_line.Printf("%s", alias_result.c_str());
3440 if (cmd_obj) {
3441 wants_raw_input = cmd_obj->WantsRawCommandString();
3442 }
3443 } else {
3444 if (cmd_obj) {
3445 llvm::StringRef cmd_name = cmd_obj->GetCommandName();
3446 revised_command_line.Printf("%s", cmd_name.str().c_str());
3447 wants_raw_input = cmd_obj->WantsRawCommandString();
3448 } else {
3449 revised_command_line.Printf("%s", next_word.c_str());
3450 }
3451 }
3452 } else {
3453 if (cmd_obj->IsMultiwordObject()) {
3454 CommandObject *sub_cmd_obj =
3455 cmd_obj->GetSubcommandObject(next_word.c_str());
3456 if (sub_cmd_obj) {
3457 // The subcommand's name includes the parent command's name, so
3458 // restart rather than append to the revised_command_line.
3459 llvm::StringRef sub_cmd_name = sub_cmd_obj->GetCommandName();
3460 revised_command_line.Clear();
3461 revised_command_line.Printf("%s", sub_cmd_name.str().c_str());
3462 cmd_obj = sub_cmd_obj;
3463 wants_raw_input = cmd_obj->WantsRawCommandString();
3464 } else {
3465 if (quote_char)
3466 revised_command_line.Printf(" %c%s%s%c", quote_char,
3467 next_word.c_str(), suffix.c_str(),
3468 quote_char);
3469 else
3470 revised_command_line.Printf(" %s%s", next_word.c_str(),
3471 suffix.c_str());
3472 done = true;
3473 }
3474 } else {
3475 if (quote_char)
3476 revised_command_line.Printf(" %c%s%s%c", quote_char,
3477 next_word.c_str(), suffix.c_str(),
3478 quote_char);
3479 else
3480 revised_command_line.Printf(" %s%s", next_word.c_str(),
3481 suffix.c_str());
3482 done = true;
3483 }
3484 }
3485
3486 if (cmd_obj == nullptr) {
3487 const size_t num_matches = matches.GetSize();
3488 if (matches.GetSize() > 1) {
3489 StreamString error_msg;
3490 error_msg.Printf("Ambiguous command '%s'. Possible matches:\n",
3491 next_word.c_str());
3492
3493 for (uint32_t i = 0; i < num_matches; ++i) {
3494 error_msg.Printf("\t%s\n", matches.GetStringAtIndex(i));
3495 }
3496 result.AppendRawError(error_msg.GetString());
3497 } else {
3498 // We didn't have only one match, otherwise we wouldn't get here.
3499 lldbassert(num_matches == 0);
3500 result.AppendErrorWithFormat("'%s' is not a valid command.\n",
3501 next_word.c_str());
3502 }
3503 return nullptr;
3504 }
3505
3506 if (cmd_obj->IsMultiwordObject()) {
3507 if (!suffix.empty()) {
3508 result.AppendErrorWithFormat(
3509 "command '%s' did not recognize '%s%s%s' as valid (subcommand "
3510 "might be invalid).\n",
3511 cmd_obj->GetCommandName().str().c_str(),
3512 next_word.empty() ? "" : next_word.c_str(),
3513 next_word.empty() ? " -- " : " ", suffix.c_str());
3514 return nullptr;
3515 }
3516 } else {
3517 // If we found a normal command, we are done
3518 done = true;
3519 if (!suffix.empty()) {
3520 switch (suffix[0]) {
3521 case '/':
3522 // GDB format suffixes
3523 {
3524 Options *command_options = cmd_obj->GetOptions();
3525 if (command_options &&
3526 command_options->SupportsLongOption("gdb-format")) {
3527 std::string gdb_format_option("--gdb-format=");
3528 gdb_format_option += (suffix.c_str() + 1);
3529
3530 std::string cmd = std::string(revised_command_line.GetString());
3531 size_t arg_terminator_idx = FindArgumentTerminator(cmd);
3532 if (arg_terminator_idx != std::string::npos) {
3533 // Insert the gdb format option before the "--" that terminates
3534 // options
3535 gdb_format_option.append(1, ' ');
3536 cmd.insert(arg_terminator_idx, gdb_format_option);
3537 revised_command_line.Clear();
3538 revised_command_line.PutCString(cmd);
3539 } else
3540 revised_command_line.Printf(" %s", gdb_format_option.c_str());
3541
3542 if (wants_raw_input &&
3543 FindArgumentTerminator(cmd) == std::string::npos)
3544 revised_command_line.PutCString(" --");
3545 } else {
3546 result.AppendErrorWithFormat(
3547 "the '%s' command doesn't support the --gdb-format option\n",
3548 cmd_obj->GetCommandName().str().c_str());
3549 return nullptr;
3550 }
3551 }
3552 break;
3553
3554 default:
3555 result.AppendErrorWithFormat(
3556 "unknown command shorthand suffix: '%s'\n", suffix.c_str());
3557 return nullptr;
3558 }
3559 }
3560 }
3561 if (scratch_command.empty())
3562 done = true;
3563 }
3564
3565 if (!scratch_command.empty())
3566 revised_command_line.Printf(" %s", scratch_command.c_str());
3567
3568 if (cmd_obj != nullptr)
3569 command_line = std::string(revised_command_line.GetString());
3570
3571 return cmd_obj;
3572}
3573
3575 llvm::json::Object stats;
3576 for (const auto &command_usage : m_command_usages)
3577 stats.try_emplace(command_usage.getKey(), command_usage.getValue());
3578 return stats;
3579}
3580
3582 return m_transcript;
3583}
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:446
#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:359
#define LLDB_LOGF(log,...)
Definition: Log.h:366
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:293
void Shift()
Shifts the first argument C string value of the array off the argument array.
Definition: Args.cpp:285
void SetArguments(size_t argc, const char **argv)
Sets the argument vector value, optionally copying all arguments into an internal buffer.
Definition: Args.cpp:357
size_t GetArgumentCount() const
Gets the number of arguments left in this command object.
Definition: Args.h:116
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:322
llvm::ArrayRef< ArgEntry > entries() const
Definition: Args.h:128
const char * GetArgumentAtIndex(size_t idx) const
Gets the NULL terminated C string argument pointer for the argument at index idx.
Definition: Args.cpp:263
const char ** GetConstArgumentVector() const
Gets the argument vector.
Definition: Args.cpp:279
void Clear()
Clear the arguments.
Definition: Args.cpp:378
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()
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
Implements dwim-print, a printing command that chooses the most direct, efficient,...
lldb::CommandObjectSP GetSubcommandSPExact(llvm::StringRef sub_cmd) override
CommandObjectMultiword * GetAsMultiwordCommand() override
virtual bool WantsRawCommandString()=0
llvm::StringRef GetCommandName() const
bool HelpTextContainsWord(llvm::StringRef search_word, bool search_short_help=true, bool search_long_help=true, bool search_syntax=true, bool search_options=true)
virtual bool IsMultiwordObject()
virtual void Execute(const char *args_string, CommandReturnObject &result)=0
virtual std::optional< std::string > GetRepeatCommand(Args &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...
std::map< std::string, lldb::CommandObjectSP > CommandMap
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)
void AppendErrorWithFormat(const char *format,...) __attribute__((format(printf
void AppendMessageWithFormat(const char *format,...) __attribute__((format(printf
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:1068
bool StartEventHandlerThread()
Manually start the global event handler thread.
Definition: Debugger.cpp:1988
void StopEventHandlerThread()
Manually stop the debugger's default event handler.
Definition: Debugger.cpp:2028
void SetAsyncExecution(bool async)
Definition: Debugger.cpp:984
HostThread SetIOHandlerThread(HostThread &new_thread)
Definition: Debugger.cpp:2140
lldb::FileSP GetInputFileSP()
Definition: Debugger.h:134
bool IsTopIOHandler(const lldb::IOHandlerSP &reader_sp)
Definition: Debugger.cpp:1155
bool IsIOHandlerThreadCurrentThread() const
Definition: Debugger.cpp:2176
uint64_t GetTerminalWidth() const
Definition: Debugger.cpp:367
const char * GetIOHandlerCommandPrefix()
Definition: Debugger.cpp:1177
bool GetUseColor() const
Definition: Debugger.cpp:403
void RunIOHandlerAsync(const lldb::IOHandlerSP &reader_sp, bool cancel_top_handler=true)
Run the given IO handler and return immediately.
Definition: Debugger.cpp:1189
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:488
void RunIOHandlerSync(const lldb::IOHandlerSP &reader_sp)
Run the given IO handler and block until it's complete.
Definition: Debugger.cpp:1124
lldb::StreamFileSP GetOutputStreamSP()
Definition: Debugger.h:136
ScriptInterpreter * GetScriptInterpreter(bool can_create=true, std::optional< lldb::ScriptLanguage > language={})
Definition: Debugger.cpp:1684
llvm::StringRef GetExternalEditor() const
Definition: Debugger.cpp:392
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:1754
A class that measures elapsed time in an exception safe way.
Definition: Statistics.h:68
void SetUnwindOnError(bool unwind=false)
Definition: Target.h:343
void SetKeepInMemory(bool keep=true)
Definition: Target.h:353
void SetCoerceToId(bool coerce=true)
Definition: Target.h:339
void SetTryAllThreads(bool try_others=true)
Definition: Target.h:376
void SetTimeout(const Timeout< std::micro > &timeout)
Definition: Target.h:364
void SetIgnoreBreakpoints(bool ignore=false)
Definition: Target.h:347
"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:190
lldb::StreamFileSP GetErrorStreamFileSP()
Definition: IOHandler.cpp:107
virtual const char * GetPrompt()
Definition: IOHandler.h:98
std::recursive_mutex & GetOutputMutex()
Definition: IOHandler.h:164
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:86
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:330
lldb::PlatformSP GetSelectedPlatform()
Select the active platform.
Definition: Platform.h:1040
A plug-in interface definition class for debugging a process.
Definition: Process.h:341
lldb::StateType GetState()
Get accessor for the current process state.
Definition: Process.cpp:1332
Status Halt(bool clear_thread_plans=false, bool use_run_lock=true)
Halts a running process.
Definition: Process.cpp:3311
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:33
An error handling class.
Definition: Status.h:44
void SetErrorStringWithFormatv(const char *format, Args &&... args)
Definition: Status.h:169
void Clear()
Clear the object state.
Definition: Status.cpp:166
int SetErrorStringWithFormat(const char *format,...) __attribute__((format(printf
Set the current error string to a formatted error string.
Definition: Status.cpp:246
void SetErrorString(llvm::StringRef err_str)
Set the current error string to err_str.
Definition: Status.cpp:232
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:4716
static TargetProperties & GetGlobalProperties()
Definition: Target.cpp:3048
lldb::PlatformSP GetPlatform()
Definition: Target.h:1444
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:2650
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:331
int AddNamesMatchingPartialString(const std::map< std::string, ValueType > &in_map, llvm::StringRef cmd_str, StringList &matches, StringList *descriptions=nullptr)
Definition: CommandObject.h:37
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
size_t FindLongestCommandWord(std::map< std::string, ValueType > &dict)
Definition: CommandObject.h:57
@ RewriteLine
The full line has been rewritten by the completion.
LoadCWDlldbinitFile
Definition: Target.h:56
@ eLoadCWDlldbinitTrue
Definition: Target.h:57
@ eLoadCWDlldbinitFalse
Definition: Target.h:58
@ eLoadCWDlldbinitWarn
Definition: Target.h:59
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:384
std::shared_ptr< lldb_private::IOHandler > IOHandlerSP
Definition: lldb-forward.h:358
std::shared_ptr< lldb_private::CommandObject > CommandObjectSP
Definition: lldb-forward.h:330
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
Definition: lldb-forward.h:479
std::unique_ptr< lldb_private::File > FileUP
Definition: lldb-forward.h:349
@ 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:475
std::shared_ptr< lldb_private::Platform > PlatformSP
Definition: lldb-forward.h:385
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:386
std::shared_ptr< lldb_private::Event > EventSP
Definition: lldb-forward.h:342
@ eReturnStatusStarted
@ eReturnStatusSuccessContinuingResult
@ eReturnStatusFailed
@ eReturnStatusSuccessContinuingNoResult
@ eReturnStatusQuit
@ eReturnStatusSuccessFinishResult
@ eReturnStatusInvalid
@ eReturnStatusSuccessFinishNoResult
std::shared_ptr< lldb_private::StreamFile > StreamFileSP
Definition: lldb-forward.h:428
std::shared_ptr< lldb_private::StopInfo > StopInfoSP
Definition: lldb-forward.h:426
StopReason
Thread stop reasons.
@ eStopReasonInstrumentation
@ eStopReasonProcessorTrace
@ eStopReasonException
@ eStopReasonSignal
std::shared_ptr< lldb_private::Target > TargetSP
Definition: lldb-forward.h:443
std::shared_ptr< lldb_private::File > FileSP
Definition: lldb-forward.h:350
const char * c_str() const
Definition: Args.h:49
llvm::StringRef ref() const
Definition: Args.h:48
char GetQuoteChar() const
Definition: Args.h:53
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