1ac7ddfbfSEd Maste //===-- CommandObjectExpression.cpp -----------------------------*- C++ -*-===//
2ac7ddfbfSEd Maste //
3ac7ddfbfSEd Maste // The LLVM Compiler Infrastructure
4ac7ddfbfSEd Maste //
5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source
6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details.
7ac7ddfbfSEd Maste //
8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===//
9ac7ddfbfSEd Maste
104bb0738eSEd Maste #include "llvm/ADT/STLExtras.h"
114bb0738eSEd Maste #include "llvm/ADT/StringRef.h"
124bb0738eSEd Maste
134bb0738eSEd Maste #include "CommandObjectExpression.h"
14435933ddSDimitry Andric #include "Plugins/ExpressionParser/Clang/ClangExpressionVariable.h"
15435933ddSDimitry Andric #include "lldb/Core/Debugger.h"
16ac7ddfbfSEd Maste #include "lldb/Core/Value.h"
17ac7ddfbfSEd Maste #include "lldb/Core/ValueObjectVariable.h"
1835617911SEd Maste #include "lldb/DataFormatters/ValueObjectPrinter.h"
19ac7ddfbfSEd Maste #include "lldb/Expression/DWARFExpression.h"
209f2f44ceSEd Maste #include "lldb/Expression/REPL.h"
21435933ddSDimitry Andric #include "lldb/Expression/UserExpression.h"
22ac7ddfbfSEd Maste #include "lldb/Host/Host.h"
23f678e45dSDimitry Andric #include "lldb/Host/OptionParser.h"
24ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandInterpreter.h"
25ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandReturnObject.h"
264ba319b5SDimitry Andric #include "lldb/Interpreter/OptionArgParser.h"
27ac7ddfbfSEd Maste #include "lldb/Symbol/ObjectFile.h"
28ac7ddfbfSEd Maste #include "lldb/Symbol/Variable.h"
29435933ddSDimitry Andric #include "lldb/Target/Language.h"
30ac7ddfbfSEd Maste #include "lldb/Target/Process.h"
31ac7ddfbfSEd Maste #include "lldb/Target/StackFrame.h"
32ac7ddfbfSEd Maste #include "lldb/Target/Target.h"
33ac7ddfbfSEd Maste #include "lldb/Target/Thread.h"
34ac7ddfbfSEd Maste
35ac7ddfbfSEd Maste using namespace lldb;
36ac7ddfbfSEd Maste using namespace lldb_private;
37ac7ddfbfSEd Maste
CommandOptions()38435933ddSDimitry Andric CommandObjectExpression::CommandOptions::CommandOptions() : OptionGroup() {}
39ac7ddfbfSEd Maste
404bb0738eSEd Maste CommandObjectExpression::CommandOptions::~CommandOptions() = default;
41ac7ddfbfSEd Maste
42*b5893f02SDimitry Andric static constexpr OptionEnumValueElement g_description_verbosity_type[] = {
43435933ddSDimitry Andric {eLanguageRuntimeDescriptionDisplayVerbosityCompact, "compact",
44435933ddSDimitry Andric "Only show the description string"},
45435933ddSDimitry Andric {eLanguageRuntimeDescriptionDisplayVerbosityFull, "full",
46*b5893f02SDimitry Andric "Show the full output, including persistent variable's name and type"} };
4735617911SEd Maste
DescriptionVerbosityTypes()48*b5893f02SDimitry Andric static constexpr OptionEnumValues DescriptionVerbosityTypes() {
49*b5893f02SDimitry Andric return OptionEnumValues(g_description_verbosity_type);
50*b5893f02SDimitry Andric }
51*b5893f02SDimitry Andric
52*b5893f02SDimitry Andric static constexpr OptionDefinition g_expression_options[] = {
53435933ddSDimitry Andric // clang-format off
54*b5893f02SDimitry Andric {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "all-threads", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Should we run all threads if the execution doesn't complete on one thread."},
55*b5893f02SDimitry Andric {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "ignore-breakpoints", 'i', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Ignore breakpoint hits while running expressions"},
56*b5893f02SDimitry Andric {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "timeout", 't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Timeout value (in microseconds) for running the expression."},
57*b5893f02SDimitry Andric {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "unwind-on-error", 'u', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Clean up program state if the expression causes a crash, or raises a signal. "
58435933ddSDimitry Andric "Note, unlike gdb hitting a breakpoint is controlled by another option (-i)."},
59*b5893f02SDimitry Andric {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "debug", 'g', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "When specified, debug the JIT code by setting a breakpoint on the first instruction "
60435933ddSDimitry Andric "and forcing breakpoints to not be ignored (-i0) and no unwinding to happen on error (-u0)."},
61*b5893f02SDimitry Andric {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Specifies the Language to use when parsing the expression. If not set the target.language "
62435933ddSDimitry Andric "setting is used." },
63*b5893f02SDimitry Andric {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "apply-fixits", 'X', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "If true, simple fix-it hints will be automatically applied to the expression." },
64*b5893f02SDimitry Andric {LLDB_OPT_SET_1, false, "description-verbosity", 'v', OptionParser::eOptionalArgument, nullptr, DescriptionVerbosityTypes(), 0, eArgTypeDescriptionVerbosity, "How verbose should the output of this expression be, if the object description is asked for."},
65*b5893f02SDimitry Andric {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "top-level", 'p', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Interpret the expression as a complete translation unit, without injecting it into the local "
66435933ddSDimitry Andric "context. Allows declaration of persistent, top-level entities without a $ prefix."},
67*b5893f02SDimitry Andric {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "allow-jit", 'j', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Controls whether the expression can fall back to being JITted if it's not supported by "
68435933ddSDimitry Andric "the interpreter (defaults to true)."}
69435933ddSDimitry Andric // clang-format on
70ac7ddfbfSEd Maste };
71ac7ddfbfSEd Maste
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)725517e702SDimitry Andric Status CommandObjectExpression::CommandOptions::SetOptionValue(
73435933ddSDimitry Andric uint32_t option_idx, llvm::StringRef option_arg,
74435933ddSDimitry Andric ExecutionContext *execution_context) {
755517e702SDimitry Andric Status error;
76ac7ddfbfSEd Maste
77435933ddSDimitry Andric const int short_option = GetDefinitions()[option_idx].short_option;
78ac7ddfbfSEd Maste
79435933ddSDimitry Andric switch (short_option) {
809f2f44ceSEd Maste case 'l':
819f2f44ceSEd Maste language = Language::GetLanguageTypeFromString(option_arg);
829f2f44ceSEd Maste if (language == eLanguageTypeUnknown)
83435933ddSDimitry Andric error.SetErrorStringWithFormat(
84435933ddSDimitry Andric "unknown language type: '%s' for expression",
85435933ddSDimitry Andric option_arg.str().c_str());
869f2f44ceSEd Maste break;
87ac7ddfbfSEd Maste
88435933ddSDimitry Andric case 'a': {
89ac7ddfbfSEd Maste bool success;
90ac7ddfbfSEd Maste bool result;
914ba319b5SDimitry Andric result = OptionArgParser::ToBoolean(option_arg, true, &success);
92ac7ddfbfSEd Maste if (!success)
93435933ddSDimitry Andric error.SetErrorStringWithFormat(
94435933ddSDimitry Andric "invalid all-threads value setting: \"%s\"",
95435933ddSDimitry Andric option_arg.str().c_str());
96ac7ddfbfSEd Maste else
97ac7ddfbfSEd Maste try_all_threads = result;
98435933ddSDimitry Andric } break;
99ac7ddfbfSEd Maste
100435933ddSDimitry Andric case 'i': {
101ac7ddfbfSEd Maste bool success;
1024ba319b5SDimitry Andric bool tmp_value = OptionArgParser::ToBoolean(option_arg, true, &success);
103ac7ddfbfSEd Maste if (success)
104ac7ddfbfSEd Maste ignore_breakpoints = tmp_value;
105ac7ddfbfSEd Maste else
106435933ddSDimitry Andric error.SetErrorStringWithFormat(
107435933ddSDimitry Andric "could not convert \"%s\" to a boolean value.",
108435933ddSDimitry Andric option_arg.str().c_str());
109ac7ddfbfSEd Maste break;
110ac7ddfbfSEd Maste }
1114bb0738eSEd Maste
112435933ddSDimitry Andric case 'j': {
1134bb0738eSEd Maste bool success;
1144ba319b5SDimitry Andric bool tmp_value = OptionArgParser::ToBoolean(option_arg, true, &success);
1154bb0738eSEd Maste if (success)
1164bb0738eSEd Maste allow_jit = tmp_value;
1174bb0738eSEd Maste else
118435933ddSDimitry Andric error.SetErrorStringWithFormat(
119435933ddSDimitry Andric "could not convert \"%s\" to a boolean value.",
120435933ddSDimitry Andric option_arg.str().c_str());
1214bb0738eSEd Maste break;
1224bb0738eSEd Maste }
1234bb0738eSEd Maste
124ac7ddfbfSEd Maste case 't':
125435933ddSDimitry Andric if (option_arg.getAsInteger(0, timeout)) {
126435933ddSDimitry Andric timeout = 0;
127435933ddSDimitry Andric error.SetErrorStringWithFormat("invalid timeout setting \"%s\"",
128435933ddSDimitry Andric option_arg.str().c_str());
129ac7ddfbfSEd Maste }
130ac7ddfbfSEd Maste break;
131ac7ddfbfSEd Maste
132435933ddSDimitry Andric case 'u': {
133ac7ddfbfSEd Maste bool success;
1344ba319b5SDimitry Andric bool tmp_value = OptionArgParser::ToBoolean(option_arg, true, &success);
135ac7ddfbfSEd Maste if (success)
136ac7ddfbfSEd Maste unwind_on_error = tmp_value;
137ac7ddfbfSEd Maste else
138435933ddSDimitry Andric error.SetErrorStringWithFormat(
139435933ddSDimitry Andric "could not convert \"%s\" to a boolean value.",
140435933ddSDimitry Andric option_arg.str().c_str());
141ac7ddfbfSEd Maste break;
142ac7ddfbfSEd Maste }
14335617911SEd Maste
14435617911SEd Maste case 'v':
145435933ddSDimitry Andric if (option_arg.empty()) {
14635617911SEd Maste m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityFull;
14735617911SEd Maste break;
14835617911SEd Maste }
1494ba319b5SDimitry Andric m_verbosity = (LanguageRuntimeDescriptionDisplayVerbosity)
1504ba319b5SDimitry Andric OptionArgParser::ToOptionEnum(
151435933ddSDimitry Andric option_arg, GetDefinitions()[option_idx].enum_values, 0, error);
15235617911SEd Maste if (!error.Success())
153435933ddSDimitry Andric error.SetErrorStringWithFormat(
154435933ddSDimitry Andric "unrecognized value for description-verbosity '%s'",
155435933ddSDimitry Andric option_arg.str().c_str());
15635617911SEd Maste break;
15735617911SEd Maste
15835617911SEd Maste case 'g':
15935617911SEd Maste debug = true;
16035617911SEd Maste unwind_on_error = false;
16135617911SEd Maste ignore_breakpoints = false;
16235617911SEd Maste break;
16335617911SEd Maste
1644bb0738eSEd Maste case 'p':
1654bb0738eSEd Maste top_level = true;
1664bb0738eSEd Maste break;
1674bb0738eSEd Maste
168435933ddSDimitry Andric case 'X': {
1694bb0738eSEd Maste bool success;
1704ba319b5SDimitry Andric bool tmp_value = OptionArgParser::ToBoolean(option_arg, true, &success);
1714bb0738eSEd Maste if (success)
1724bb0738eSEd Maste auto_apply_fixits = tmp_value ? eLazyBoolYes : eLazyBoolNo;
1734bb0738eSEd Maste else
174435933ddSDimitry Andric error.SetErrorStringWithFormat(
175435933ddSDimitry Andric "could not convert \"%s\" to a boolean value.",
176435933ddSDimitry Andric option_arg.str().c_str());
1774bb0738eSEd Maste break;
1784bb0738eSEd Maste }
1794bb0738eSEd Maste
180ac7ddfbfSEd Maste default:
181435933ddSDimitry Andric error.SetErrorStringWithFormat("invalid short option character '%c'",
182435933ddSDimitry Andric short_option);
183ac7ddfbfSEd Maste break;
184ac7ddfbfSEd Maste }
185ac7ddfbfSEd Maste
186ac7ddfbfSEd Maste return error;
187ac7ddfbfSEd Maste }
188ac7ddfbfSEd Maste
OptionParsingStarting(ExecutionContext * execution_context)189435933ddSDimitry Andric void CommandObjectExpression::CommandOptions::OptionParsingStarting(
190435933ddSDimitry Andric ExecutionContext *execution_context) {
191435933ddSDimitry Andric auto process_sp =
192435933ddSDimitry Andric execution_context ? execution_context->GetProcessSP() : ProcessSP();
193435933ddSDimitry Andric if (process_sp) {
194435933ddSDimitry Andric ignore_breakpoints = process_sp->GetIgnoreBreakpointsInExpressions();
195435933ddSDimitry Andric unwind_on_error = process_sp->GetUnwindOnErrorInExpressions();
196435933ddSDimitry Andric } else {
1970127ef0fSEd Maste ignore_breakpoints = true;
198ac7ddfbfSEd Maste unwind_on_error = true;
199ac7ddfbfSEd Maste }
200ac7ddfbfSEd Maste
201ac7ddfbfSEd Maste show_summary = true;
202ac7ddfbfSEd Maste try_all_threads = true;
203ac7ddfbfSEd Maste timeout = 0;
20435617911SEd Maste debug = false;
2059f2f44ceSEd Maste language = eLanguageTypeUnknown;
20635617911SEd Maste m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityCompact;
2074bb0738eSEd Maste auto_apply_fixits = eLazyBoolCalculate;
2084bb0738eSEd Maste top_level = false;
2094bb0738eSEd Maste allow_jit = true;
210ac7ddfbfSEd Maste }
211ac7ddfbfSEd Maste
212435933ddSDimitry Andric llvm::ArrayRef<OptionDefinition>
GetDefinitions()213435933ddSDimitry Andric CommandObjectExpression::CommandOptions::GetDefinitions() {
214435933ddSDimitry Andric return llvm::makeArrayRef(g_expression_options);
215ac7ddfbfSEd Maste }
216ac7ddfbfSEd Maste
CommandObjectExpression(CommandInterpreter & interpreter)217435933ddSDimitry Andric CommandObjectExpression::CommandObjectExpression(
218435933ddSDimitry Andric CommandInterpreter &interpreter)
2194bb0738eSEd Maste : CommandObjectRaw(
220435933ddSDimitry Andric interpreter, "expression", "Evaluate an expression on the current "
221435933ddSDimitry Andric "thread. Displays any returned value "
222435933ddSDimitry Andric "with LLDB's default formatting.",
223435933ddSDimitry Andric "", eCommandProcessMustBePaused | eCommandTryTargetAPILock),
22412b93ac6SEd Maste IOHandlerDelegate(IOHandlerDelegate::Completion::Expression),
225435933ddSDimitry Andric m_option_group(), m_format_options(eFormatDefault),
226435933ddSDimitry Andric m_repl_option(LLDB_OPT_SET_1, false, "repl", 'r', "Drop into REPL", false,
227435933ddSDimitry Andric true),
228435933ddSDimitry Andric m_command_options(), m_expr_line_count(0), m_expr_lines() {
229ac7ddfbfSEd Maste SetHelpLong(
230b91a7dfcSDimitry Andric R"(
231acac075bSDimitry Andric Single and multi-line expressions:
232acac075bSDimitry Andric
233acac075bSDimitry Andric )"
234acac075bSDimitry Andric " The expression provided on the command line must be a complete expression \
235acac075bSDimitry Andric with no newlines. To evaluate a multi-line expression, \
236acac075bSDimitry Andric hit a return after an empty expression, and lldb will enter the multi-line expression editor. \
237acac075bSDimitry Andric Hit return on an empty line to end the multi-line expression."
238acac075bSDimitry Andric
239acac075bSDimitry Andric R"(
240acac075bSDimitry Andric
241b91a7dfcSDimitry Andric Timeouts:
242b91a7dfcSDimitry Andric
243435933ddSDimitry Andric )"
244435933ddSDimitry Andric " If the expression can be evaluated statically (without running code) then it will be. \
245b91a7dfcSDimitry Andric Otherwise, by default the expression will run on the current thread with a short timeout: \
246b91a7dfcSDimitry Andric currently .25 seconds. If it doesn't return in that time, the evaluation will be interrupted \
247b91a7dfcSDimitry Andric and resumed with all threads running. You can use the -a option to disable retrying on all \
248435933ddSDimitry Andric threads. You can use the -t option to set a shorter timeout."
249435933ddSDimitry Andric R"(
250b91a7dfcSDimitry Andric
251b91a7dfcSDimitry Andric User defined variables:
252b91a7dfcSDimitry Andric
253435933ddSDimitry Andric )"
254435933ddSDimitry Andric " You can define your own variables for convenience or to be used in subsequent expressions. \
255b91a7dfcSDimitry Andric You define them the same way you would define variables in C. If the first character of \
256b91a7dfcSDimitry Andric your user defined variable is a $, then the variable's value will be available in future \
257435933ddSDimitry Andric expressions, otherwise it will just be available in the current expression."
258435933ddSDimitry Andric R"(
259b91a7dfcSDimitry Andric
260b91a7dfcSDimitry Andric Continuing evaluation after a breakpoint:
261b91a7dfcSDimitry Andric
262435933ddSDimitry Andric )"
263435933ddSDimitry Andric " If the \"-i false\" option is used, and execution is interrupted by a breakpoint hit, once \
264b91a7dfcSDimitry Andric you are done with your investigation, you can either remove the expression execution frames \
265b91a7dfcSDimitry Andric from the stack with \"thread return -x\" or if you are still interested in the expression result \
266b91a7dfcSDimitry Andric you can issue the \"continue\" command and the expression evaluation will complete and the \
267b91a7dfcSDimitry Andric expression result will be available using the \"thread.completed-expression\" key in the thread \
268435933ddSDimitry Andric format."
269acac075bSDimitry Andric
270435933ddSDimitry Andric R"(
271b91a7dfcSDimitry Andric
272b91a7dfcSDimitry Andric Examples:
273b91a7dfcSDimitry Andric
274b91a7dfcSDimitry Andric expr my_struct->a = my_array[3]
275b91a7dfcSDimitry Andric expr -f bin -- (index * 8) + 5
276b91a7dfcSDimitry Andric expr unsigned int $foo = 5
277435933ddSDimitry Andric expr char c[] = \"foo\"; c[0])");
278ac7ddfbfSEd Maste
279ac7ddfbfSEd Maste CommandArgumentEntry arg;
280ac7ddfbfSEd Maste CommandArgumentData expression_arg;
281ac7ddfbfSEd Maste
282ac7ddfbfSEd Maste // Define the first (and only) variant of this arg.
283ac7ddfbfSEd Maste expression_arg.arg_type = eArgTypeExpression;
284ac7ddfbfSEd Maste expression_arg.arg_repetition = eArgRepeatPlain;
285ac7ddfbfSEd Maste
286435933ddSDimitry Andric // There is only one variant this argument could be; put it into the argument
287435933ddSDimitry Andric // entry.
288ac7ddfbfSEd Maste arg.push_back(expression_arg);
289ac7ddfbfSEd Maste
290ac7ddfbfSEd Maste // Push the data for the first argument into the m_arguments vector.
291ac7ddfbfSEd Maste m_arguments.push_back(arg);
292ac7ddfbfSEd Maste
293ac7ddfbfSEd Maste // Add the "--format" and "--gdb-format"
294435933ddSDimitry Andric m_option_group.Append(&m_format_options,
295435933ddSDimitry Andric OptionGroupFormat::OPTION_GROUP_FORMAT |
296435933ddSDimitry Andric OptionGroupFormat::OPTION_GROUP_GDB_FMT,
297435933ddSDimitry Andric LLDB_OPT_SET_1);
298ac7ddfbfSEd Maste m_option_group.Append(&m_command_options);
299435933ddSDimitry Andric m_option_group.Append(&m_varobj_options, LLDB_OPT_SET_ALL,
300435933ddSDimitry Andric LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
3019f2f44ceSEd Maste m_option_group.Append(&m_repl_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
302ac7ddfbfSEd Maste m_option_group.Finalize();
303ac7ddfbfSEd Maste }
304ac7ddfbfSEd Maste
3054bb0738eSEd Maste CommandObjectExpression::~CommandObjectExpression() = default;
306ac7ddfbfSEd Maste
GetOptions()307435933ddSDimitry Andric Options *CommandObjectExpression::GetOptions() { return &m_option_group; }
308ac7ddfbfSEd Maste
HandleCompletion(CompletionRequest & request)309*b5893f02SDimitry Andric int CommandObjectExpression::HandleCompletion(CompletionRequest &request) {
310*b5893f02SDimitry Andric EvaluateExpressionOptions options;
311*b5893f02SDimitry Andric options.SetCoerceToId(m_varobj_options.use_objc);
312*b5893f02SDimitry Andric options.SetLanguage(m_command_options.language);
313*b5893f02SDimitry Andric options.SetExecutionPolicy(lldb_private::eExecutionPolicyNever);
314*b5893f02SDimitry Andric options.SetAutoApplyFixIts(false);
315*b5893f02SDimitry Andric options.SetGenerateDebugInfo(false);
316*b5893f02SDimitry Andric
317*b5893f02SDimitry Andric // We need a valid execution context with a frame pointer for this
318*b5893f02SDimitry Andric // completion, so if we don't have one we should try to make a valid
319*b5893f02SDimitry Andric // execution context.
320*b5893f02SDimitry Andric if (m_interpreter.GetExecutionContext().GetFramePtr() == nullptr)
321*b5893f02SDimitry Andric m_interpreter.UpdateExecutionContext(nullptr);
322*b5893f02SDimitry Andric
323*b5893f02SDimitry Andric // This didn't work, so let's get out before we start doing things that
324*b5893f02SDimitry Andric // expect a valid frame pointer.
325*b5893f02SDimitry Andric if (m_interpreter.GetExecutionContext().GetFramePtr() == nullptr)
326*b5893f02SDimitry Andric return 0;
327*b5893f02SDimitry Andric
328*b5893f02SDimitry Andric ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
329*b5893f02SDimitry Andric
330*b5893f02SDimitry Andric Target *target = exe_ctx.GetTargetPtr();
331*b5893f02SDimitry Andric
332*b5893f02SDimitry Andric if (!target)
333*b5893f02SDimitry Andric target = GetDummyTarget();
334*b5893f02SDimitry Andric
335*b5893f02SDimitry Andric if (!target)
336*b5893f02SDimitry Andric return 0;
337*b5893f02SDimitry Andric
338*b5893f02SDimitry Andric unsigned cursor_pos = request.GetRawCursorPos();
339*b5893f02SDimitry Andric llvm::StringRef code = request.GetRawLine();
340*b5893f02SDimitry Andric
341*b5893f02SDimitry Andric const std::size_t original_code_size = code.size();
342*b5893f02SDimitry Andric
343*b5893f02SDimitry Andric // Remove the first token which is 'expr' or some alias/abbreviation of that.
344*b5893f02SDimitry Andric code = llvm::getToken(code).second.ltrim();
345*b5893f02SDimitry Andric OptionsWithRaw args(code);
346*b5893f02SDimitry Andric code = args.GetRawPart();
347*b5893f02SDimitry Andric
348*b5893f02SDimitry Andric // The position where the expression starts in the command line.
349*b5893f02SDimitry Andric assert(original_code_size >= code.size());
350*b5893f02SDimitry Andric std::size_t raw_start = original_code_size - code.size();
351*b5893f02SDimitry Andric
352*b5893f02SDimitry Andric // Check if the cursor is actually in the expression string, and if not, we
353*b5893f02SDimitry Andric // exit.
354*b5893f02SDimitry Andric // FIXME: We should complete the options here.
355*b5893f02SDimitry Andric if (cursor_pos < raw_start)
356*b5893f02SDimitry Andric return 0;
357*b5893f02SDimitry Andric
358*b5893f02SDimitry Andric // Make the cursor_pos again relative to the start of the code string.
359*b5893f02SDimitry Andric assert(cursor_pos >= raw_start);
360*b5893f02SDimitry Andric cursor_pos -= raw_start;
361*b5893f02SDimitry Andric
362*b5893f02SDimitry Andric auto language = exe_ctx.GetFrameRef().GetLanguage();
363*b5893f02SDimitry Andric
364*b5893f02SDimitry Andric Status error;
365*b5893f02SDimitry Andric lldb::UserExpressionSP expr(target->GetUserExpressionForLanguage(
366*b5893f02SDimitry Andric code, llvm::StringRef(), language, UserExpression::eResultTypeAny,
367*b5893f02SDimitry Andric options, error));
368*b5893f02SDimitry Andric if (error.Fail())
369*b5893f02SDimitry Andric return 0;
370*b5893f02SDimitry Andric
371*b5893f02SDimitry Andric expr->Complete(exe_ctx, request, cursor_pos);
372*b5893f02SDimitry Andric return request.GetNumberOfMatches();
373*b5893f02SDimitry Andric }
374*b5893f02SDimitry Andric
3755517e702SDimitry Andric static lldb_private::Status
CanBeUsedForElementCountPrinting(ValueObject & valobj)376435933ddSDimitry Andric CanBeUsedForElementCountPrinting(ValueObject &valobj) {
3774bb0738eSEd Maste CompilerType type(valobj.GetCompilerType());
3784bb0738eSEd Maste CompilerType pointee;
3794bb0738eSEd Maste if (!type.IsPointerType(&pointee))
3805517e702SDimitry Andric return Status("as it does not refer to a pointer");
3814bb0738eSEd Maste if (pointee.IsVoidType())
3825517e702SDimitry Andric return Status("as it refers to a pointer to void");
3835517e702SDimitry Andric return Status();
3844bb0738eSEd Maste }
3854bb0738eSEd Maste
EvaluateExpression(llvm::StringRef expr,Stream * output_stream,Stream * error_stream,CommandReturnObject * result)3864ba319b5SDimitry Andric bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr,
387ac7ddfbfSEd Maste Stream *output_stream,
388ac7ddfbfSEd Maste Stream *error_stream,
389435933ddSDimitry Andric CommandReturnObject *result) {
3904ba319b5SDimitry Andric // Don't use m_exe_ctx as this might be called asynchronously after the
3914ba319b5SDimitry Andric // command object DoExecute has finished when doing multi-line expression
3924ba319b5SDimitry Andric // that use an input reader...
393ac7ddfbfSEd Maste ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
394ac7ddfbfSEd Maste
395ac7ddfbfSEd Maste Target *target = exe_ctx.GetTargetPtr();
396ac7ddfbfSEd Maste
397ac7ddfbfSEd Maste if (!target)
3987aa51b79SEd Maste target = GetDummyTarget();
399ac7ddfbfSEd Maste
400435933ddSDimitry Andric if (target) {
401ac7ddfbfSEd Maste lldb::ValueObjectSP result_valobj_sp;
402ac7ddfbfSEd Maste bool keep_in_memory = true;
4039f2f44ceSEd Maste StackFrame *frame = exe_ctx.GetFramePtr();
404ac7ddfbfSEd Maste
405ac7ddfbfSEd Maste EvaluateExpressionOptions options;
406b952cd58SEd Maste options.SetCoerceToId(m_varobj_options.use_objc);
407b952cd58SEd Maste options.SetUnwindOnError(m_command_options.unwind_on_error);
408b952cd58SEd Maste options.SetIgnoreBreakpoints(m_command_options.ignore_breakpoints);
409b952cd58SEd Maste options.SetKeepInMemory(keep_in_memory);
410b952cd58SEd Maste options.SetUseDynamic(m_varobj_options.use_dynamic);
411b952cd58SEd Maste options.SetTryAllThreads(m_command_options.try_all_threads);
412b952cd58SEd Maste options.SetDebug(m_command_options.debug);
4139f2f44ceSEd Maste options.SetLanguage(m_command_options.language);
414435933ddSDimitry Andric options.SetExecutionPolicy(
415435933ddSDimitry Andric m_command_options.allow_jit
416435933ddSDimitry Andric ? EvaluateExpressionOptions::default_execution_policy
417435933ddSDimitry Andric : lldb_private::eExecutionPolicyNever);
4184bb0738eSEd Maste
4194bb0738eSEd Maste bool auto_apply_fixits;
4204bb0738eSEd Maste if (m_command_options.auto_apply_fixits == eLazyBoolCalculate)
4214bb0738eSEd Maste auto_apply_fixits = target->GetEnableAutoApplyFixIts();
4224bb0738eSEd Maste else
423*b5893f02SDimitry Andric auto_apply_fixits = m_command_options.auto_apply_fixits == eLazyBoolYes;
4244bb0738eSEd Maste
4254bb0738eSEd Maste options.SetAutoApplyFixIts(auto_apply_fixits);
4264bb0738eSEd Maste
4274bb0738eSEd Maste if (m_command_options.top_level)
4284bb0738eSEd Maste options.SetExecutionPolicy(eExecutionPolicyTopLevel);
42935617911SEd Maste
4304ba319b5SDimitry Andric // If there is any chance we are going to stop and want to see what went
4314ba319b5SDimitry Andric // wrong with our expression, we should generate debug info
4320127ef0fSEd Maste if (!m_command_options.ignore_breakpoints ||
4330127ef0fSEd Maste !m_command_options.unwind_on_error)
4340127ef0fSEd Maste options.SetGenerateDebugInfo(true);
4350127ef0fSEd Maste
43635617911SEd Maste if (m_command_options.timeout > 0)
437435933ddSDimitry Andric options.SetTimeout(std::chrono::microseconds(m_command_options.timeout));
43812b93ac6SEd Maste else
439435933ddSDimitry Andric options.SetTimeout(llvm::None);
440ac7ddfbfSEd Maste
441435933ddSDimitry Andric ExpressionResults success = target->EvaluateExpression(
442435933ddSDimitry Andric expr, frame, result_valobj_sp, options, &m_fixed_expression);
4434bb0738eSEd Maste
444435933ddSDimitry Andric // We only tell you about the FixIt if we applied it. The compiler errors
445435933ddSDimitry Andric // will suggest the FixIt if it parsed.
446435933ddSDimitry Andric if (error_stream && !m_fixed_expression.empty() &&
447435933ddSDimitry Andric target->GetEnableNotifyAboutFixIts()) {
4484bb0738eSEd Maste if (success == eExpressionCompleted)
449435933ddSDimitry Andric error_stream->Printf(
450435933ddSDimitry Andric " Fix-it applied, fixed expression was: \n %s\n",
451435933ddSDimitry Andric m_fixed_expression.c_str());
4524bb0738eSEd Maste }
453ac7ddfbfSEd Maste
454435933ddSDimitry Andric if (result_valobj_sp) {
455ac7ddfbfSEd Maste Format format = m_format_options.GetFormat();
456ac7ddfbfSEd Maste
457435933ddSDimitry Andric if (result_valobj_sp->GetError().Success()) {
458435933ddSDimitry Andric if (format != eFormatVoid) {
459ac7ddfbfSEd Maste if (format != eFormatDefault)
460ac7ddfbfSEd Maste result_valobj_sp->SetFormat(format);
461ac7ddfbfSEd Maste
462435933ddSDimitry Andric if (m_varobj_options.elem_count > 0) {
4635517e702SDimitry Andric Status error(CanBeUsedForElementCountPrinting(*result_valobj_sp));
464435933ddSDimitry Andric if (error.Fail()) {
465435933ddSDimitry Andric result->AppendErrorWithFormat(
466435933ddSDimitry Andric "expression cannot be used with --element-count %s\n",
467435933ddSDimitry Andric error.AsCString(""));
4684bb0738eSEd Maste result->SetStatus(eReturnStatusFailed);
4694bb0738eSEd Maste return false;
4704bb0738eSEd Maste }
4714bb0738eSEd Maste }
4724bb0738eSEd Maste
473435933ddSDimitry Andric DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(
474435933ddSDimitry Andric m_command_options.m_verbosity, format));
475435933ddSDimitry Andric options.SetVariableFormatDisplayLanguage(
476435933ddSDimitry Andric result_valobj_sp->GetPreferredDisplayLanguage());
477ac7ddfbfSEd Maste
47835617911SEd Maste result_valobj_sp->Dump(*output_stream, options);
47935617911SEd Maste
480ac7ddfbfSEd Maste if (result)
481ac7ddfbfSEd Maste result->SetStatus(eReturnStatusSuccessFinishResult);
482ac7ddfbfSEd Maste }
483435933ddSDimitry Andric } else {
484435933ddSDimitry Andric if (result_valobj_sp->GetError().GetError() ==
485435933ddSDimitry Andric UserExpression::kNoResult) {
486435933ddSDimitry Andric if (format != eFormatVoid &&
487435933ddSDimitry Andric m_interpreter.GetDebugger().GetNotifyVoid()) {
488ac7ddfbfSEd Maste error_stream->PutCString("(void)\n");
489ac7ddfbfSEd Maste }
490ac7ddfbfSEd Maste
491ac7ddfbfSEd Maste if (result)
492ac7ddfbfSEd Maste result->SetStatus(eReturnStatusSuccessFinishResult);
493435933ddSDimitry Andric } else {
494ac7ddfbfSEd Maste const char *error_cstr = result_valobj_sp->GetError().AsCString();
495435933ddSDimitry Andric if (error_cstr && error_cstr[0]) {
496ac7ddfbfSEd Maste const size_t error_cstr_len = strlen(error_cstr);
497435933ddSDimitry Andric const bool ends_with_newline =
498435933ddSDimitry Andric error_cstr[error_cstr_len - 1] == '\n';
499ac7ddfbfSEd Maste if (strstr(error_cstr, "error:") != error_cstr)
500ac7ddfbfSEd Maste error_stream->PutCString("error: ");
501ac7ddfbfSEd Maste error_stream->Write(error_cstr, error_cstr_len);
502ac7ddfbfSEd Maste if (!ends_with_newline)
503ac7ddfbfSEd Maste error_stream->EOL();
504435933ddSDimitry Andric } else {
505ac7ddfbfSEd Maste error_stream->PutCString("error: unknown error\n");
506ac7ddfbfSEd Maste }
507ac7ddfbfSEd Maste
508ac7ddfbfSEd Maste if (result)
509ac7ddfbfSEd Maste result->SetStatus(eReturnStatusFailed);
510ac7ddfbfSEd Maste }
511ac7ddfbfSEd Maste }
512ac7ddfbfSEd Maste }
513435933ddSDimitry Andric } else {
514ac7ddfbfSEd Maste error_stream->Printf("error: invalid execution context for expression\n");
515ac7ddfbfSEd Maste return false;
516ac7ddfbfSEd Maste }
517ac7ddfbfSEd Maste
518ac7ddfbfSEd Maste return true;
519ac7ddfbfSEd Maste }
520ac7ddfbfSEd Maste
IOHandlerInputComplete(IOHandler & io_handler,std::string & line)521435933ddSDimitry Andric void CommandObjectExpression::IOHandlerInputComplete(IOHandler &io_handler,
522435933ddSDimitry Andric std::string &line) {
52312b93ac6SEd Maste io_handler.SetIsDone(true);
524435933ddSDimitry Andric // StreamSP output_stream =
525435933ddSDimitry Andric // io_handler.GetDebugger().GetAsyncOutputStream();
52612b93ac6SEd Maste // StreamSP error_stream = io_handler.GetDebugger().GetAsyncErrorStream();
52712b93ac6SEd Maste StreamFileSP output_sp(io_handler.GetOutputStreamFile());
52812b93ac6SEd Maste StreamFileSP error_sp(io_handler.GetErrorStreamFile());
52912b93ac6SEd Maste
530435933ddSDimitry Andric EvaluateExpression(line.c_str(), output_sp.get(), error_sp.get());
53112b93ac6SEd Maste if (output_sp)
53212b93ac6SEd Maste output_sp->Flush();
53312b93ac6SEd Maste if (error_sp)
53412b93ac6SEd Maste error_sp->Flush();
53512b93ac6SEd Maste }
53612b93ac6SEd Maste
IOHandlerIsInputComplete(IOHandler & io_handler,StringList & lines)537435933ddSDimitry Andric bool CommandObjectExpression::IOHandlerIsInputComplete(IOHandler &io_handler,
538435933ddSDimitry Andric StringList &lines) {
5394bb0738eSEd Maste // An empty lines is used to indicate the end of input
5404bb0738eSEd Maste const size_t num_lines = lines.GetSize();
541435933ddSDimitry Andric if (num_lines > 0 && lines[num_lines - 1].empty()) {
5424ba319b5SDimitry Andric // Remove the last empty line from "lines" so it doesn't appear in our
5434ba319b5SDimitry Andric // resulting input and return true to indicate we are done getting lines
54412b93ac6SEd Maste lines.PopBack();
5454bb0738eSEd Maste return true;
54612b93ac6SEd Maste }
5474bb0738eSEd Maste return false;
54812b93ac6SEd Maste }
54912b93ac6SEd Maste
GetMultilineExpression()550435933ddSDimitry Andric void CommandObjectExpression::GetMultilineExpression() {
5510127ef0fSEd Maste m_expr_lines.clear();
5520127ef0fSEd Maste m_expr_line_count = 0;
5530127ef0fSEd Maste
5540127ef0fSEd Maste Debugger &debugger = GetCommandInterpreter().GetDebugger();
5557aa51b79SEd Maste bool color_prompt = debugger.GetUseColor();
5560127ef0fSEd Maste const bool multiple_lines = true; // Get multiple lines
557435933ddSDimitry Andric IOHandlerSP io_handler_sp(
558435933ddSDimitry Andric new IOHandlerEditline(debugger, IOHandler::Type::Expression,
5590127ef0fSEd Maste "lldb-expr", // Name of input reader for history
560435933ddSDimitry Andric llvm::StringRef(), // No prompt
561435933ddSDimitry Andric llvm::StringRef(), // Continuation prompt
562435933ddSDimitry Andric multiple_lines, color_prompt,
5630127ef0fSEd Maste 1, // Show line numbers starting at 1
5640127ef0fSEd Maste *this));
5650127ef0fSEd Maste
5660127ef0fSEd Maste StreamFileSP output_sp(io_handler_sp->GetOutputStreamFile());
567435933ddSDimitry Andric if (output_sp) {
568435933ddSDimitry Andric output_sp->PutCString(
569435933ddSDimitry Andric "Enter expressions, then terminate with an empty line to evaluate:\n");
5700127ef0fSEd Maste output_sp->Flush();
5710127ef0fSEd Maste }
5720127ef0fSEd Maste debugger.PushIOHandler(io_handler_sp);
5730127ef0fSEd Maste }
5740127ef0fSEd Maste
DoExecute(llvm::StringRef command,CommandReturnObject & result)5754ba319b5SDimitry Andric bool CommandObjectExpression::DoExecute(llvm::StringRef command,
576435933ddSDimitry Andric CommandReturnObject &result) {
5774bb0738eSEd Maste m_fixed_expression.clear();
578435933ddSDimitry Andric auto exe_ctx = GetCommandInterpreter().GetExecutionContext();
579435933ddSDimitry Andric m_option_group.NotifyOptionParsingStarting(&exe_ctx);
580ac7ddfbfSEd Maste
5814ba319b5SDimitry Andric if (command.empty()) {
5820127ef0fSEd Maste GetMultilineExpression();
583ac7ddfbfSEd Maste return result.Succeeded();
584ac7ddfbfSEd Maste }
585ac7ddfbfSEd Maste
5864ba319b5SDimitry Andric OptionsWithRaw args(command);
5874ba319b5SDimitry Andric llvm::StringRef expr = args.GetRawPart();
588ac7ddfbfSEd Maste
5894ba319b5SDimitry Andric if (args.HasArgs()) {
5904ba319b5SDimitry Andric if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group, exe_ctx))
591ac7ddfbfSEd Maste return false;
592ac7ddfbfSEd Maste
593435933ddSDimitry Andric if (m_repl_option.GetOptionValue().GetCurrentValue()) {
5949f2f44ceSEd Maste Target *target = m_interpreter.GetExecutionContext().GetTargetPtr();
595435933ddSDimitry Andric if (target) {
5969f2f44ceSEd Maste // Drop into REPL
5979f2f44ceSEd Maste m_expr_lines.clear();
5989f2f44ceSEd Maste m_expr_line_count = 0;
5999f2f44ceSEd Maste
6009f2f44ceSEd Maste Debugger &debugger = target->GetDebugger();
6019f2f44ceSEd Maste
602435933ddSDimitry Andric // Check if the LLDB command interpreter is sitting on top of a REPL
6034ba319b5SDimitry Andric // that launched it...
6044ba319b5SDimitry Andric if (debugger.CheckTopIOHandlerTypes(IOHandler::Type::CommandInterpreter,
6054ba319b5SDimitry Andric IOHandler::Type::REPL)) {
606435933ddSDimitry Andric // the LLDB command interpreter is sitting on top of a REPL that
6074ba319b5SDimitry Andric // launched it, so just say the command interpreter is done and
6084ba319b5SDimitry Andric // fall back to the existing REPL
6099f2f44ceSEd Maste m_interpreter.GetIOHandler(false)->SetIsDone(true);
610435933ddSDimitry Andric } else {
611435933ddSDimitry Andric // We are launching the REPL on top of the current LLDB command
6124ba319b5SDimitry Andric // interpreter, so just push one
6139f2f44ceSEd Maste bool initialize = false;
6145517e702SDimitry Andric Status repl_error;
6154ba319b5SDimitry Andric REPLSP repl_sp(target->GetREPL(repl_error, m_command_options.language,
6164ba319b5SDimitry Andric nullptr, false));
6179f2f44ceSEd Maste
618435933ddSDimitry Andric if (!repl_sp) {
6199f2f44ceSEd Maste initialize = true;
620435933ddSDimitry Andric repl_sp = target->GetREPL(repl_error, m_command_options.language,
621435933ddSDimitry Andric nullptr, true);
622435933ddSDimitry Andric if (!repl_error.Success()) {
6239f2f44ceSEd Maste result.SetError(repl_error);
6249f2f44ceSEd Maste return result.Succeeded();
6259f2f44ceSEd Maste }
6269f2f44ceSEd Maste }
6279f2f44ceSEd Maste
628435933ddSDimitry Andric if (repl_sp) {
629435933ddSDimitry Andric if (initialize) {
6309f2f44ceSEd Maste repl_sp->SetCommandOptions(m_command_options);
6319f2f44ceSEd Maste repl_sp->SetFormatOptions(m_format_options);
6329f2f44ceSEd Maste repl_sp->SetValueObjectDisplayOptions(m_varobj_options);
6339f2f44ceSEd Maste }
6349f2f44ceSEd Maste
6359f2f44ceSEd Maste IOHandlerSP io_handler_sp(repl_sp->GetIOHandler());
6369f2f44ceSEd Maste
6379f2f44ceSEd Maste io_handler_sp->SetIsDone(false);
6389f2f44ceSEd Maste
6399f2f44ceSEd Maste debugger.PushIOHandler(io_handler_sp);
640435933ddSDimitry Andric } else {
641435933ddSDimitry Andric repl_error.SetErrorStringWithFormat(
642435933ddSDimitry Andric "Couldn't create a REPL for %s",
643435933ddSDimitry Andric Language::GetNameForLanguageType(m_command_options.language));
6449f2f44ceSEd Maste result.SetError(repl_error);
6459f2f44ceSEd Maste return result.Succeeded();
6469f2f44ceSEd Maste }
6479f2f44ceSEd Maste }
6489f2f44ceSEd Maste }
6499f2f44ceSEd Maste }
6500127ef0fSEd Maste // No expression following options
6514ba319b5SDimitry Andric else if (expr.empty()) {
6520127ef0fSEd Maste GetMultilineExpression();
6530127ef0fSEd Maste return result.Succeeded();
6540127ef0fSEd Maste }
655ac7ddfbfSEd Maste }
656ac7ddfbfSEd Maste
6574ba319b5SDimitry Andric Target *target = GetSelectedOrDummyTarget();
658435933ddSDimitry Andric if (EvaluateExpression(expr, &(result.GetOutputStream()),
659435933ddSDimitry Andric &(result.GetErrorStream()), &result)) {
660435933ddSDimitry Andric
661435933ddSDimitry Andric if (!m_fixed_expression.empty() && target->GetEnableNotifyAboutFixIts()) {
6624bb0738eSEd Maste CommandHistory &history = m_interpreter.GetCommandHistory();
663435933ddSDimitry Andric // FIXME: Can we figure out what the user actually typed (e.g. some alias
664435933ddSDimitry Andric // for expr???)
6654bb0738eSEd Maste // If we can it would be nice to show that.
6664bb0738eSEd Maste std::string fixed_command("expression ");
6674ba319b5SDimitry Andric if (args.HasArgs()) {
6684bb0738eSEd Maste // Add in any options that might have been in the original command:
6694ba319b5SDimitry Andric fixed_command.append(args.GetArgStringWithDelimiter());
6704bb0738eSEd Maste fixed_command.append(m_fixed_expression);
6714ba319b5SDimitry Andric } else
6724ba319b5SDimitry Andric fixed_command.append(m_fixed_expression);
6734bb0738eSEd Maste history.AppendString(fixed_command);
6744bb0738eSEd Maste }
6754ba319b5SDimitry Andric // Increment statistics to record this expression evaluation success.
6764ba319b5SDimitry Andric target->IncrementStats(StatisticKind::ExpressionSuccessful);
677ac7ddfbfSEd Maste return true;
6784bb0738eSEd Maste }
679ac7ddfbfSEd Maste
6804ba319b5SDimitry Andric // Increment statistics to record this expression evaluation failure.
6814ba319b5SDimitry Andric target->IncrementStats(StatisticKind::ExpressionFailure);
682ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
683ac7ddfbfSEd Maste return false;
684ac7ddfbfSEd Maste }
685