CommandObjectExpression.cpp revision 269024
1//===-- CommandObjectExpression.cpp -----------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/lldb-python.h"
11
12#include "CommandObjectExpression.h"
13
14// C Includes
15// C++ Includes
16// Other libraries and framework includes
17// Project includes
18#include "lldb/Interpreter/Args.h"
19#include "lldb/Core/Value.h"
20#include "lldb/Core/ValueObjectVariable.h"
21#include "lldb/DataFormatters/ValueObjectPrinter.h"
22#include "lldb/Expression/ClangExpressionVariable.h"
23#include "lldb/Expression/ClangUserExpression.h"
24#include "lldb/Expression/ClangFunction.h"
25#include "lldb/Expression/DWARFExpression.h"
26#include "lldb/Host/Host.h"
27#include "lldb/Core/Debugger.h"
28#include "lldb/Interpreter/CommandInterpreter.h"
29#include "lldb/Interpreter/CommandReturnObject.h"
30#include "lldb/Target/ObjCLanguageRuntime.h"
31#include "lldb/Symbol/ObjectFile.h"
32#include "lldb/Symbol/Variable.h"
33#include "lldb/Target/Process.h"
34#include "lldb/Target/StackFrame.h"
35#include "lldb/Target/Target.h"
36#include "lldb/Target/Thread.h"
37#include "llvm/ADT/StringRef.h"
38
39using namespace lldb;
40using namespace lldb_private;
41
42CommandObjectExpression::CommandOptions::CommandOptions () :
43    OptionGroup()
44{
45}
46
47
48CommandObjectExpression::CommandOptions::~CommandOptions ()
49{
50}
51
52static OptionEnumValueElement g_description_verbosity_type[] =
53{
54    { eLanguageRuntimeDescriptionDisplayVerbosityCompact,      "compact",       "Only show the description string"},
55    { eLanguageRuntimeDescriptionDisplayVerbosityFull,         "full",          "Show the full output, including persistent variable's name and type"},
56    { 0, NULL, NULL }
57};
58
59OptionDefinition
60CommandObjectExpression::CommandOptions::g_option_table[] =
61{
62    { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "all-threads",        'a', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean,    "Should we run all threads if the execution doesn't complete on one thread."},
63    { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "ignore-breakpoints", 'i', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean,    "Ignore breakpoint hits while running expressions"},
64    { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "timeout",            't', OptionParser::eRequiredArgument, NULL, 0, eArgTypeUnsignedInteger,  "Timeout value (in microseconds) for running the expression."},
65    { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "unwind-on-error",    'u', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean,    "Clean up program state if the expression causes a crash, or raises a signal.  Note, unlike gdb hitting a breakpoint is controlled by another option (-i)."},
66    { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "debug",              'g', OptionParser::eNoArgument      , NULL, 0, eArgTypeNone,       "When specified, debug the JIT code by setting a breakpoint on the first instruction and forcing breakpoints to not be ignored (-i0) and no unwinding to happen on error (-u0)."},
67    { LLDB_OPT_SET_1, false, "description-verbosity", 'v', OptionParser::eOptionalArgument, g_description_verbosity_type, 0, eArgTypeDescriptionVerbosity,        "How verbose should the output of this expression be, if the object description is asked for."},
68};
69
70
71uint32_t
72CommandObjectExpression::CommandOptions::GetNumDefinitions ()
73{
74    return sizeof(g_option_table)/sizeof(OptionDefinition);
75}
76
77Error
78CommandObjectExpression::CommandOptions::SetOptionValue (CommandInterpreter &interpreter,
79                                                         uint32_t option_idx,
80                                                         const char *option_arg)
81{
82    Error error;
83
84    const int short_option = g_option_table[option_idx].short_option;
85
86    switch (short_option)
87    {
88      //case 'l':
89      //if (language.SetLanguageFromCString (option_arg) == false)
90      //{
91      //    error.SetErrorStringWithFormat("invalid language option argument '%s'", option_arg);
92      //}
93      //break;
94
95    case 'a':
96        {
97            bool success;
98            bool result;
99            result = Args::StringToBoolean(option_arg, true, &success);
100            if (!success)
101                error.SetErrorStringWithFormat("invalid all-threads value setting: \"%s\"", option_arg);
102            else
103                try_all_threads = result;
104        }
105        break;
106
107    case 'i':
108        {
109            bool success;
110            bool tmp_value = Args::StringToBoolean(option_arg, true, &success);
111            if (success)
112                ignore_breakpoints = tmp_value;
113            else
114                error.SetErrorStringWithFormat("could not convert \"%s\" to a boolean value.", option_arg);
115            break;
116        }
117    case 't':
118        {
119            bool success;
120            uint32_t result;
121            result = Args::StringToUInt32(option_arg, 0, 0, &success);
122            if (success)
123                timeout = result;
124            else
125                error.SetErrorStringWithFormat ("invalid timeout setting \"%s\"", option_arg);
126        }
127        break;
128
129    case 'u':
130        {
131            bool success;
132            bool tmp_value = Args::StringToBoolean(option_arg, true, &success);
133            if (success)
134                unwind_on_error = tmp_value;
135            else
136                error.SetErrorStringWithFormat("could not convert \"%s\" to a boolean value.", option_arg);
137            break;
138        }
139
140    case 'v':
141        if (!option_arg)
142        {
143            m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityFull;
144            break;
145        }
146        m_verbosity = (LanguageRuntimeDescriptionDisplayVerbosity) Args::StringToOptionEnum(option_arg, g_option_table[option_idx].enum_values, 0, error);
147        if (!error.Success())
148            error.SetErrorStringWithFormat ("unrecognized value for description-verbosity '%s'", option_arg);
149        break;
150
151    case 'g':
152        debug = true;
153        unwind_on_error = false;
154        ignore_breakpoints = false;
155        break;
156
157    default:
158        error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
159        break;
160    }
161
162    return error;
163}
164
165void
166CommandObjectExpression::CommandOptions::OptionParsingStarting (CommandInterpreter &interpreter)
167{
168    Process *process = interpreter.GetExecutionContext().GetProcessPtr();
169    if (process != NULL)
170    {
171        ignore_breakpoints = process->GetIgnoreBreakpointsInExpressions();
172        unwind_on_error    = process->GetUnwindOnErrorInExpressions();
173    }
174    else
175    {
176        ignore_breakpoints = false;
177        unwind_on_error = true;
178    }
179
180    show_summary = true;
181    try_all_threads = true;
182    timeout = 0;
183    debug = false;
184    m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityCompact;
185}
186
187const OptionDefinition*
188CommandObjectExpression::CommandOptions::GetDefinitions ()
189{
190    return g_option_table;
191}
192
193CommandObjectExpression::CommandObjectExpression (CommandInterpreter &interpreter) :
194    CommandObjectRaw (interpreter,
195                      "expression",
196                      "Evaluate a C/ObjC/C++ expression in the current program context, using user defined variables and variables currently in scope.",
197                      NULL,
198                      eFlagProcessMustBePaused | eFlagTryTargetAPILock),
199    IOHandlerDelegate (IOHandlerDelegate::Completion::Expression),
200    m_option_group (interpreter),
201    m_format_options (eFormatDefault),
202    m_command_options (),
203    m_expr_line_count (0),
204    m_expr_lines ()
205{
206  SetHelpLong(
207"Timeouts:\n\
208    If the expression can be evaluated statically (without runnning code) then it will be.\n\
209    Otherwise, by default the expression will run on the current thread with a short timeout:\n\
210    currently .25 seconds.  If it doesn't return in that time, the evaluation will be interrupted\n\
211    and resumed with all threads running.  You can use the -a option to disable retrying on all\n\
212    threads.  You can use the -t option to set a shorter timeout.\n\
213\n\
214User defined variables:\n\
215    You can define your own variables for convenience or to be used in subsequent expressions.\n\
216    You define them the same way you would define variables in C.  If the first character of \n\
217    your user defined variable is a $, then the variable's value will be available in future\n\
218    expressions, otherwise it will just be available in the current expression.\n\
219\n\
220Examples: \n\
221\n\
222   expr my_struct->a = my_array[3] \n\
223   expr -f bin -- (index * 8) + 5 \n\
224   expr unsigned int $foo = 5\n\
225   expr char c[] = \"foo\"; c[0]\n");
226
227    CommandArgumentEntry arg;
228    CommandArgumentData expression_arg;
229
230    // Define the first (and only) variant of this arg.
231    expression_arg.arg_type = eArgTypeExpression;
232    expression_arg.arg_repetition = eArgRepeatPlain;
233
234    // There is only one variant this argument could be; put it into the argument entry.
235    arg.push_back (expression_arg);
236
237    // Push the data for the first argument into the m_arguments vector.
238    m_arguments.push_back (arg);
239
240    // Add the "--format" and "--gdb-format"
241    m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_GDB_FMT, LLDB_OPT_SET_1);
242    m_option_group.Append (&m_command_options);
243    m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
244    m_option_group.Finalize();
245}
246
247CommandObjectExpression::~CommandObjectExpression ()
248{
249}
250
251Options *
252CommandObjectExpression::GetOptions ()
253{
254    return &m_option_group;
255}
256
257bool
258CommandObjectExpression::EvaluateExpression
259(
260    const char *expr,
261    Stream *output_stream,
262    Stream *error_stream,
263    CommandReturnObject *result
264)
265{
266    // Don't use m_exe_ctx as this might be called asynchronously
267    // after the command object DoExecute has finished when doing
268    // multi-line expression that use an input reader...
269    ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
270
271    Target *target = exe_ctx.GetTargetPtr();
272
273    if (!target)
274        target = Host::GetDummyTarget(m_interpreter.GetDebugger()).get();
275
276    if (target)
277    {
278        lldb::ValueObjectSP result_valobj_sp;
279
280        ExecutionResults exe_results;
281
282        bool keep_in_memory = true;
283
284        EvaluateExpressionOptions options;
285        options.SetCoerceToId(m_varobj_options.use_objc);
286        options.SetUnwindOnError(m_command_options.unwind_on_error);
287        options.SetIgnoreBreakpoints (m_command_options.ignore_breakpoints);
288        options.SetKeepInMemory(keep_in_memory);
289        options.SetUseDynamic(m_varobj_options.use_dynamic);
290        options.SetTryAllThreads(m_command_options.try_all_threads);
291        options.SetDebug(m_command_options.debug);
292
293        if (m_command_options.timeout > 0)
294            options.SetTimeoutUsec(m_command_options.timeout);
295        else
296            options.SetTimeoutUsec(0);
297
298        exe_results = target->EvaluateExpression (expr,
299                                                  exe_ctx.GetFramePtr(),
300                                                  result_valobj_sp,
301                                                  options);
302
303        if (result_valobj_sp)
304        {
305            Format format = m_format_options.GetFormat();
306
307            if (result_valobj_sp->GetError().Success())
308            {
309                if (format != eFormatVoid)
310                {
311                    if (format != eFormatDefault)
312                        result_valobj_sp->SetFormat (format);
313
314                    DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(m_command_options.m_verbosity,format));
315
316                    result_valobj_sp->Dump(*output_stream,options);
317
318                    if (result)
319                        result->SetStatus (eReturnStatusSuccessFinishResult);
320                }
321            }
322            else
323            {
324                if (result_valobj_sp->GetError().GetError() == ClangUserExpression::kNoResult)
325                {
326                    if (format != eFormatVoid && m_interpreter.GetDebugger().GetNotifyVoid())
327                    {
328                        error_stream->PutCString("(void)\n");
329                    }
330
331                    if (result)
332                        result->SetStatus (eReturnStatusSuccessFinishResult);
333                }
334                else
335                {
336                    const char *error_cstr = result_valobj_sp->GetError().AsCString();
337                    if (error_cstr && error_cstr[0])
338                    {
339                        const size_t error_cstr_len = strlen (error_cstr);
340                        const bool ends_with_newline = error_cstr[error_cstr_len - 1] == '\n';
341                        if (strstr(error_cstr, "error:") != error_cstr)
342                            error_stream->PutCString ("error: ");
343                        error_stream->Write(error_cstr, error_cstr_len);
344                        if (!ends_with_newline)
345                            error_stream->EOL();
346                    }
347                    else
348                    {
349                        error_stream->PutCString ("error: unknown error\n");
350                    }
351
352                    if (result)
353                        result->SetStatus (eReturnStatusFailed);
354                }
355            }
356        }
357    }
358    else
359    {
360        error_stream->Printf ("error: invalid execution context for expression\n");
361        return false;
362    }
363
364    return true;
365}
366
367void
368CommandObjectExpression::IOHandlerInputComplete (IOHandler &io_handler, std::string &line)
369{
370    io_handler.SetIsDone(true);
371//    StreamSP output_stream = io_handler.GetDebugger().GetAsyncOutputStream();
372//    StreamSP error_stream = io_handler.GetDebugger().GetAsyncErrorStream();
373    StreamFileSP output_sp(io_handler.GetOutputStreamFile());
374    StreamFileSP error_sp(io_handler.GetErrorStreamFile());
375
376    EvaluateExpression (line.c_str(),
377                        output_sp.get(),
378                        error_sp.get());
379    if (output_sp)
380        output_sp->Flush();
381    if (error_sp)
382        error_sp->Flush();
383}
384
385LineStatus
386CommandObjectExpression::IOHandlerLinesUpdated (IOHandler &io_handler,
387                                                StringList &lines,
388                                                uint32_t line_idx,
389                                                Error &error)
390{
391    if (line_idx == UINT32_MAX)
392    {
393        // Remove the last line from "lines" so it doesn't appear
394        // in our final expression
395        lines.PopBack();
396        error.Clear();
397        return LineStatus::Done;
398    }
399    else if (line_idx + 1 == lines.GetSize())
400    {
401        // The last line was edited, if this line is empty, then we are done
402        // getting our multiple lines.
403        if (lines[line_idx].empty())
404            return LineStatus::Done;
405    }
406    return LineStatus::Success;
407}
408
409bool
410CommandObjectExpression::DoExecute
411(
412    const char *command,
413    CommandReturnObject &result
414)
415{
416    m_option_group.NotifyOptionParsingStarting();
417
418    const char * expr = NULL;
419
420    if (command[0] == '\0')
421    {
422        m_expr_lines.clear();
423        m_expr_line_count = 0;
424
425        Debugger &debugger = GetCommandInterpreter().GetDebugger();
426        const bool multiple_lines = true; // Get multiple lines
427        IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger,
428                                                          "lldb-expr",      // Name of input reader for history
429                                                          NULL,             // No prompt
430                                                          multiple_lines,
431                                                          *this));
432
433        StreamFileSP output_sp(io_handler_sp->GetOutputStreamFile());
434        if (output_sp)
435        {
436            output_sp->PutCString("Enter expressions, then terminate with an empty line to evaluate:\n");
437            output_sp->Flush();
438        }
439        debugger.PushIOHandler(io_handler_sp);
440        return result.Succeeded();
441    }
442
443    if (command[0] == '-')
444    {
445        // We have some options and these options MUST end with --.
446        const char *end_options = NULL;
447        const char *s = command;
448        while (s && s[0])
449        {
450            end_options = ::strstr (s, "--");
451            if (end_options)
452            {
453                end_options += 2; // Get past the "--"
454                if (::isspace (end_options[0]))
455                {
456                    expr = end_options;
457                    while (::isspace (*expr))
458                        ++expr;
459                    break;
460                }
461            }
462            s = end_options;
463        }
464
465        if (end_options)
466        {
467            Args args (command, end_options - command);
468            if (!ParseOptions (args, result))
469                return false;
470
471            Error error (m_option_group.NotifyOptionParsingFinished());
472            if (error.Fail())
473            {
474                result.AppendError (error.AsCString());
475                result.SetStatus (eReturnStatusFailed);
476                return false;
477            }
478        }
479    }
480
481    if (expr == NULL)
482        expr = command;
483
484    if (EvaluateExpression (expr, &(result.GetOutputStream()), &(result.GetErrorStream()), &result))
485        return true;
486
487    result.SetStatus (eReturnStatusFailed);
488    return false;
489}
490
491