]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - source/Commands/CommandObjectExpression.cpp
Import lldb as of SVN r196259 (git 3be86e5)
[FreeBSD/FreeBSD.git] / source / Commands / CommandObjectExpression.cpp
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/InputReader.h"
21 #include "lldb/Core/ValueObjectVariable.h"
22 #include "lldb/DataFormatters/ValueObjectPrinter.h"
23 #include "lldb/Expression/ClangExpressionVariable.h"
24 #include "lldb/Expression/ClangUserExpression.h"
25 #include "lldb/Expression/ClangFunction.h"
26 #include "lldb/Expression/DWARFExpression.h"
27 #include "lldb/Host/Host.h"
28 #include "lldb/Core/Debugger.h"
29 #include "lldb/Interpreter/CommandInterpreter.h"
30 #include "lldb/Interpreter/CommandReturnObject.h"
31 #include "lldb/Target/ObjCLanguageRuntime.h"
32 #include "lldb/Symbol/ObjectFile.h"
33 #include "lldb/Symbol/Variable.h"
34 #include "lldb/Target/Process.h"
35 #include "lldb/Target/StackFrame.h"
36 #include "lldb/Target/Target.h"
37 #include "lldb/Target/Thread.h"
38 #include "llvm/ADT/StringRef.h"
39
40 using namespace lldb;
41 using namespace lldb_private;
42
43 CommandObjectExpression::CommandOptions::CommandOptions () :
44     OptionGroup()
45 {
46 }
47
48
49 CommandObjectExpression::CommandOptions::~CommandOptions ()
50 {
51 }
52
53 static OptionEnumValueElement g_description_verbosity_type[] =
54 {
55     { eLanguageRuntimeDescriptionDisplayVerbosityCompact,      "compact",       "Only show the description string"},
56     { eLanguageRuntimeDescriptionDisplayVerbosityFull,         "full",          "Show the full output, including persistent variable's name and type"},
57     { 0, NULL, NULL }
58 };
59
60 OptionDefinition
61 CommandObjectExpression::CommandOptions::g_option_table[] =
62 {
63     { 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."},
64     { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "ignore-breakpoints", 'i', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean,    "Ignore breakpoint hits while running expressions"},
65     { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "timeout",            't', OptionParser::eRequiredArgument, NULL, 0, eArgTypeUnsignedInteger,  "Timeout value (in microseconds) for running the expression."},
66     { 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)."},
67     { 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)."},
68     { 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."},
69 };
70
71
72 uint32_t
73 CommandObjectExpression::CommandOptions::GetNumDefinitions ()
74 {
75     return sizeof(g_option_table)/sizeof(OptionDefinition);
76 }
77
78 Error
79 CommandObjectExpression::CommandOptions::SetOptionValue (CommandInterpreter &interpreter,
80                                                          uint32_t option_idx,
81                                                          const char *option_arg)
82 {
83     Error error;
84
85     const int short_option = g_option_table[option_idx].short_option;
86
87     switch (short_option)
88     {
89       //case 'l':
90       //if (language.SetLanguageFromCString (option_arg) == false)
91       //{
92       //    error.SetErrorStringWithFormat("invalid language option argument '%s'", option_arg);
93       //}
94       //break;
95
96     case 'a':
97         {
98             bool success;
99             bool result;
100             result = Args::StringToBoolean(option_arg, true, &success);
101             if (!success)
102                 error.SetErrorStringWithFormat("invalid all-threads value setting: \"%s\"", option_arg);
103             else
104                 try_all_threads = result;
105         }
106         break;
107         
108     case 'i':
109         {
110             bool success;
111             bool tmp_value = Args::StringToBoolean(option_arg, true, &success);
112             if (success)
113                 ignore_breakpoints = tmp_value;
114             else
115                 error.SetErrorStringWithFormat("could not convert \"%s\" to a boolean value.", option_arg);
116             break;
117         }
118     case 't':
119         {
120             bool success;
121             uint32_t result;
122             result = Args::StringToUInt32(option_arg, 0, 0, &success);
123             if (success)
124                 timeout = result;
125             else
126                 error.SetErrorStringWithFormat ("invalid timeout setting \"%s\"", option_arg);
127         }
128         break;
129         
130     case 'u':
131         {
132             bool success;
133             bool tmp_value = Args::StringToBoolean(option_arg, true, &success);
134             if (success)
135                 unwind_on_error = tmp_value;
136             else
137                 error.SetErrorStringWithFormat("could not convert \"%s\" to a boolean value.", option_arg);
138             break;
139         }
140             
141     case 'v':
142         if (!option_arg)
143         {
144             m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityFull;
145             break;
146         }
147         m_verbosity = (LanguageRuntimeDescriptionDisplayVerbosity) Args::StringToOptionEnum(option_arg, g_option_table[option_idx].enum_values, 0, error);
148         if (!error.Success())
149             error.SetErrorStringWithFormat ("unrecognized value for description-verbosity '%s'", option_arg);
150         break;
151     
152     case 'g':
153         debug = true;
154         unwind_on_error = false;
155         ignore_breakpoints = false;
156         break;
157
158     default:
159         error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
160         break;
161     }
162
163     return error;
164 }
165
166 void
167 CommandObjectExpression::CommandOptions::OptionParsingStarting (CommandInterpreter &interpreter)
168 {
169     Process *process = interpreter.GetExecutionContext().GetProcessPtr();
170     if (process != NULL)
171     {
172         ignore_breakpoints = process->GetIgnoreBreakpointsInExpressions();
173         unwind_on_error    = process->GetUnwindOnErrorInExpressions();
174     }
175     else
176     {
177         ignore_breakpoints = false;
178         unwind_on_error = true;
179     }
180     
181     show_summary = true;
182     try_all_threads = true;
183     timeout = 0;
184     debug = false;
185     m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityCompact;
186 }
187
188 const OptionDefinition*
189 CommandObjectExpression::CommandOptions::GetDefinitions ()
190 {
191     return g_option_table;
192 }
193
194 CommandObjectExpression::CommandObjectExpression (CommandInterpreter &interpreter) :
195     CommandObjectRaw (interpreter,
196                       "expression",
197                       "Evaluate a C/ObjC/C++ expression in the current program context, using user defined variables and variables currently in scope.",
198                       NULL,
199                       eFlagProcessMustBePaused | eFlagTryTargetAPILock),
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\
214 User 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\
220 Examples: \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
247 CommandObjectExpression::~CommandObjectExpression ()
248 {
249 }
250
251 Options *
252 CommandObjectExpression::GetOptions ()
253 {
254     return &m_option_group;
255 }
256
257 size_t
258 CommandObjectExpression::MultiLineExpressionCallback
259 (
260     void *baton, 
261     InputReader &reader, 
262     lldb::InputReaderAction notification,
263     const char *bytes, 
264     size_t bytes_len
265 )
266 {
267     CommandObjectExpression *cmd_object_expr = (CommandObjectExpression *) baton;
268     bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
269     
270     switch (notification)
271     {
272     case eInputReaderActivate:
273         if (!batch_mode)
274         {
275             StreamSP async_strm_sp(reader.GetDebugger().GetAsyncOutputStream());
276             if (async_strm_sp)
277             {
278                 async_strm_sp->PutCString("Enter expressions, then terminate with an empty line to evaluate:\n");
279                 async_strm_sp->Flush();
280             }
281         }
282         // Fall through
283     case eInputReaderReactivate:
284         break;
285
286     case eInputReaderDeactivate:
287         break;
288
289     case eInputReaderAsynchronousOutputWritten:
290         break;
291         
292     case eInputReaderGotToken:
293         ++cmd_object_expr->m_expr_line_count;
294         if (bytes && bytes_len)
295         {
296             cmd_object_expr->m_expr_lines.append (bytes, bytes_len + 1);
297         }
298
299         if (bytes_len == 0)
300             reader.SetIsDone(true);
301         break;
302         
303     case eInputReaderInterrupt:
304         cmd_object_expr->m_expr_lines.clear();
305         reader.SetIsDone (true);
306         if (!batch_mode)
307         {
308             StreamSP async_strm_sp (reader.GetDebugger().GetAsyncOutputStream());
309             if (async_strm_sp)
310             {
311                 async_strm_sp->PutCString("Expression evaluation cancelled.\n");
312                 async_strm_sp->Flush();
313             }
314         }
315         break;
316         
317     case eInputReaderEndOfFile:
318         reader.SetIsDone (true);
319         break;
320         
321     case eInputReaderDone:
322                 if (cmd_object_expr->m_expr_lines.size() > 0)
323         {
324             StreamSP output_stream = reader.GetDebugger().GetAsyncOutputStream();
325             StreamSP error_stream = reader.GetDebugger().GetAsyncErrorStream();
326             cmd_object_expr->EvaluateExpression (cmd_object_expr->m_expr_lines.c_str(), 
327                                                  output_stream.get(), 
328                                                  error_stream.get());
329             output_stream->Flush();
330             error_stream->Flush();
331         }
332         break;
333     }
334
335     return bytes_len;
336 }
337
338 bool
339 CommandObjectExpression::EvaluateExpression 
340 (
341     const char *expr, 
342     Stream *output_stream, 
343     Stream *error_stream,
344     CommandReturnObject *result
345 )
346 {
347     // Don't use m_exe_ctx as this might be called asynchronously
348     // after the command object DoExecute has finished when doing
349     // multi-line expression that use an input reader...
350     ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
351
352     Target *target = exe_ctx.GetTargetPtr();
353     
354     if (!target)
355         target = Host::GetDummyTarget(m_interpreter.GetDebugger()).get();
356     
357     if (target)
358     {
359         lldb::ValueObjectSP result_valobj_sp;
360
361         ExecutionResults exe_results;
362         
363         bool keep_in_memory = true;
364
365         EvaluateExpressionOptions options;
366         options.SetCoerceToId(m_varobj_options.use_objc);
367         options.SetUnwindOnError(m_command_options.unwind_on_error);
368         options.SetIgnoreBreakpoints (m_command_options.ignore_breakpoints);
369         options.SetKeepInMemory(keep_in_memory);
370         options.SetUseDynamic(m_varobj_options.use_dynamic);
371         options.SetTryAllThreads(m_command_options.try_all_threads);
372         options.SetDebug(m_command_options.debug);
373         
374         if (m_command_options.timeout > 0)
375             options.SetTimeoutUsec(m_command_options.timeout);
376         
377         exe_results = target->EvaluateExpression (expr, 
378                                                   exe_ctx.GetFramePtr(),
379                                                   result_valobj_sp,
380                                                   options);
381
382         if (result_valobj_sp)
383         {
384             Format format = m_format_options.GetFormat();
385
386             if (result_valobj_sp->GetError().Success())
387             {
388                 if (format != eFormatVoid)
389                 {
390                     if (format != eFormatDefault)
391                         result_valobj_sp->SetFormat (format);
392
393                     DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(m_command_options.m_verbosity,format));
394
395                     result_valobj_sp->Dump(*output_stream,options);
396                     
397                     if (result)
398                         result->SetStatus (eReturnStatusSuccessFinishResult);
399                 }
400             }
401             else
402             {
403                 if (result_valobj_sp->GetError().GetError() == ClangUserExpression::kNoResult)
404                 {
405                     if (format != eFormatVoid && m_interpreter.GetDebugger().GetNotifyVoid())
406                     {
407                         error_stream->PutCString("(void)\n");
408                     }
409                     
410                     if (result)
411                         result->SetStatus (eReturnStatusSuccessFinishResult);
412                 }
413                 else
414                 {
415                     const char *error_cstr = result_valobj_sp->GetError().AsCString();
416                     if (error_cstr && error_cstr[0])
417                     {
418                         const size_t error_cstr_len = strlen (error_cstr);
419                         const bool ends_with_newline = error_cstr[error_cstr_len - 1] == '\n';
420                         if (strstr(error_cstr, "error:") != error_cstr)
421                             error_stream->PutCString ("error: ");
422                         error_stream->Write(error_cstr, error_cstr_len);
423                         if (!ends_with_newline)
424                             error_stream->EOL();
425                     }
426                     else
427                     {
428                         error_stream->PutCString ("error: unknown error\n");
429                     }
430                     
431                     if (result)
432                         result->SetStatus (eReturnStatusFailed);
433                 }
434             }
435         }
436     }
437     else
438     {
439         error_stream->Printf ("error: invalid execution context for expression\n");
440         return false;
441     }
442         
443     return true;
444 }
445
446 bool
447 CommandObjectExpression::DoExecute
448 (
449     const char *command,
450     CommandReturnObject &result
451 )
452 {
453     m_option_group.NotifyOptionParsingStarting();
454
455     const char * expr = NULL;
456
457     if (command[0] == '\0')
458     {
459         m_expr_lines.clear();
460         m_expr_line_count = 0;
461         
462         InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
463         if (reader_sp)
464         {
465             Error err (reader_sp->Initialize (CommandObjectExpression::MultiLineExpressionCallback,
466                                               this,                         // baton
467                                               eInputReaderGranularityLine,  // token size, to pass to callback function
468                                               NULL,                         // end token
469                                               NULL,                         // prompt
470                                               true));                       // echo input
471             if (err.Success())
472             {
473                 m_interpreter.GetDebugger().PushInputReader (reader_sp);
474                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
475             }
476             else
477             {
478                 result.AppendError (err.AsCString());
479                 result.SetStatus (eReturnStatusFailed);
480             }
481         }
482         else
483         {
484             result.AppendError("out of memory");
485             result.SetStatus (eReturnStatusFailed);
486         }
487         return result.Succeeded();
488     }
489
490     if (command[0] == '-')
491     {
492         // We have some options and these options MUST end with --.
493         const char *end_options = NULL;
494         const char *s = command;
495         while (s && s[0])
496         {
497             end_options = ::strstr (s, "--");
498             if (end_options)
499             {
500                 end_options += 2; // Get past the "--"
501                 if (::isspace (end_options[0]))
502                 {
503                     expr = end_options;
504                     while (::isspace (*expr))
505                         ++expr;
506                     break;
507                 }
508             }
509             s = end_options;
510         }
511
512         if (end_options)
513         {
514             Args args (command, end_options - command);
515             if (!ParseOptions (args, result))
516                 return false;
517             
518             Error error (m_option_group.NotifyOptionParsingFinished());
519             if (error.Fail())
520             {
521                 result.AppendError (error.AsCString());
522                 result.SetStatus (eReturnStatusFailed);
523                 return false;
524             }
525         }
526     }
527
528     if (expr == NULL)
529         expr = command;
530     
531     if (EvaluateExpression (expr, &(result.GetOutputStream()), &(result.GetErrorStream()), &result))
532         return true;
533
534     result.SetStatus (eReturnStatusFailed);
535     return false;
536 }
537