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