]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/llvm/tools/lldb/source/Commands/CommandObjectExpression.cpp
Copy head (r256279) to stable/10 as part of the 10.0-RELEASE cycle.
[FreeBSD/stable/10.git] / contrib / llvm / tools / lldb / 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/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
39 using namespace lldb;
40 using namespace lldb_private;
41
42 CommandObjectExpression::CommandOptions::CommandOptions () :
43     OptionGroup()
44 {
45 }
46
47
48 CommandObjectExpression::CommandOptions::~CommandOptions ()
49 {
50 }
51
52 OptionDefinition
53 CommandObjectExpression::CommandOptions::g_option_table[] =
54 {
55     { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "all-threads",        'a', required_argument, NULL, 0, eArgTypeBoolean,    "Should we run all threads if the execution doesn't complete on one thread."},
56     { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "ignore-breakpoints", 'i', required_argument, NULL, 0, eArgTypeBoolean,    "Ignore breakpoint hits while running expressions"},
57     { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "timeout",            't', required_argument, NULL, 0, eArgTypeUnsignedInteger,  "Timeout value (in microseconds) for running the expression."},
58     { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "unwind-on-error",    'u', required_argument, 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)."},
59 };
60
61
62 uint32_t
63 CommandObjectExpression::CommandOptions::GetNumDefinitions ()
64 {
65     return sizeof(g_option_table)/sizeof(OptionDefinition);
66 }
67
68 Error
69 CommandObjectExpression::CommandOptions::SetOptionValue (CommandInterpreter &interpreter,
70                                                          uint32_t option_idx,
71                                                          const char *option_arg)
72 {
73     Error error;
74
75     const int short_option = g_option_table[option_idx].short_option;
76
77     switch (short_option)
78     {
79       //case 'l':
80       //if (language.SetLanguageFromCString (option_arg) == false)
81       //{
82       //    error.SetErrorStringWithFormat("invalid language option argument '%s'", option_arg);
83       //}
84       //break;
85
86     case 'a':
87         {
88             bool success;
89             bool result;
90             result = Args::StringToBoolean(option_arg, true, &success);
91             if (!success)
92                 error.SetErrorStringWithFormat("invalid all-threads value setting: \"%s\"", option_arg);
93             else
94                 try_all_threads = result;
95         }
96         break;
97         
98     case 'i':
99         {
100             bool success;
101             bool tmp_value = Args::StringToBoolean(option_arg, true, &success);
102             if (success)
103                 ignore_breakpoints = tmp_value;
104             else
105                 error.SetErrorStringWithFormat("could not convert \"%s\" to a boolean value.", option_arg);
106             break;
107         }
108     case 't':
109         {
110             bool success;
111             uint32_t result;
112             result = Args::StringToUInt32(option_arg, 0, 0, &success);
113             if (success)
114                 timeout = result;
115             else
116                 error.SetErrorStringWithFormat ("invalid timeout setting \"%s\"", option_arg);
117         }
118         break;
119         
120     case 'u':
121         {
122             bool success;
123             bool tmp_value = Args::StringToBoolean(option_arg, true, &success);
124             if (success)
125                 unwind_on_error = tmp_value;
126             else
127                 error.SetErrorStringWithFormat("could not convert \"%s\" to a boolean value.", option_arg);
128             break;
129         }
130     default:
131         error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
132         break;
133     }
134
135     return error;
136 }
137
138 void
139 CommandObjectExpression::CommandOptions::OptionParsingStarting (CommandInterpreter &interpreter)
140 {
141     Process *process = interpreter.GetExecutionContext().GetProcessPtr();
142     if (process != NULL)
143     {
144         ignore_breakpoints = process->GetIgnoreBreakpointsInExpressions();
145         unwind_on_error    = process->GetUnwindOnErrorInExpressions();
146     }
147     else
148     {
149         ignore_breakpoints = false;
150         unwind_on_error = true;
151     }
152     
153     show_summary = true;
154     try_all_threads = true;
155     timeout = 0;
156 }
157
158 const OptionDefinition*
159 CommandObjectExpression::CommandOptions::GetDefinitions ()
160 {
161     return g_option_table;
162 }
163
164 CommandObjectExpression::CommandObjectExpression (CommandInterpreter &interpreter) :
165     CommandObjectRaw (interpreter,
166                       "expression",
167                       "Evaluate a C/ObjC/C++ expression in the current program context, using user defined variables and variables currently in scope.",
168                       NULL,
169                       eFlagProcessMustBePaused | eFlagTryTargetAPILock),
170     m_option_group (interpreter),
171     m_format_options (eFormatDefault),
172     m_command_options (),
173     m_expr_line_count (0),
174     m_expr_lines ()
175 {
176   SetHelpLong(
177 "Timeouts:\n\
178     If the expression can be evaluated statically (without runnning code) then it will be.\n\
179     Otherwise, by default the expression will run on the current thread with a short timeout:\n\
180     currently .25 seconds.  If it doesn't return in that time, the evaluation will be interrupted\n\
181     and resumed with all threads running.  You can use the -a option to disable retrying on all\n\
182     threads.  You can use the -t option to set a shorter timeout.\n\
183 \n\
184 User defined variables:\n\
185     You can define your own variables for convenience or to be used in subsequent expressions.\n\
186     You define them the same way you would define variables in C.  If the first character of \n\
187     your user defined variable is a $, then the variable's value will be available in future\n\
188     expressions, otherwise it will just be available in the current expression.\n\
189 \n\
190 Examples: \n\
191 \n\
192    expr my_struct->a = my_array[3] \n\
193    expr -f bin -- (index * 8) + 5 \n\
194    expr unsigned int $foo = 5\n\
195    expr char c[] = \"foo\"; c[0]\n");
196
197     CommandArgumentEntry arg;
198     CommandArgumentData expression_arg;
199
200     // Define the first (and only) variant of this arg.
201     expression_arg.arg_type = eArgTypeExpression;
202     expression_arg.arg_repetition = eArgRepeatPlain;
203
204     // There is only one variant this argument could be; put it into the argument entry.
205     arg.push_back (expression_arg);
206
207     // Push the data for the first argument into the m_arguments vector.
208     m_arguments.push_back (arg);
209     
210     // Add the "--format" and "--gdb-format"
211     m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_GDB_FMT, LLDB_OPT_SET_1);
212     m_option_group.Append (&m_command_options);
213     m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
214     m_option_group.Finalize();
215 }
216
217 CommandObjectExpression::~CommandObjectExpression ()
218 {
219 }
220
221 Options *
222 CommandObjectExpression::GetOptions ()
223 {
224     return &m_option_group;
225 }
226
227 size_t
228 CommandObjectExpression::MultiLineExpressionCallback
229 (
230     void *baton, 
231     InputReader &reader, 
232     lldb::InputReaderAction notification,
233     const char *bytes, 
234     size_t bytes_len
235 )
236 {
237     CommandObjectExpression *cmd_object_expr = (CommandObjectExpression *) baton;
238     bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
239     
240     switch (notification)
241     {
242     case eInputReaderActivate:
243         if (!batch_mode)
244         {
245             StreamSP async_strm_sp(reader.GetDebugger().GetAsyncOutputStream());
246             if (async_strm_sp)
247             {
248                 async_strm_sp->PutCString("Enter expressions, then terminate with an empty line to evaluate:\n");
249                 async_strm_sp->Flush();
250             }
251         }
252         // Fall through
253     case eInputReaderReactivate:
254         break;
255
256     case eInputReaderDeactivate:
257         break;
258
259     case eInputReaderAsynchronousOutputWritten:
260         break;
261         
262     case eInputReaderGotToken:
263         ++cmd_object_expr->m_expr_line_count;
264         if (bytes && bytes_len)
265         {
266             cmd_object_expr->m_expr_lines.append (bytes, bytes_len + 1);
267         }
268
269         if (bytes_len == 0)
270             reader.SetIsDone(true);
271         break;
272         
273     case eInputReaderInterrupt:
274         cmd_object_expr->m_expr_lines.clear();
275         reader.SetIsDone (true);
276         if (!batch_mode)
277         {
278             StreamSP async_strm_sp (reader.GetDebugger().GetAsyncOutputStream());
279             if (async_strm_sp)
280             {
281                 async_strm_sp->PutCString("Expression evaluation cancelled.\n");
282                 async_strm_sp->Flush();
283             }
284         }
285         break;
286         
287     case eInputReaderEndOfFile:
288         reader.SetIsDone (true);
289         break;
290         
291     case eInputReaderDone:
292                 if (cmd_object_expr->m_expr_lines.size() > 0)
293         {
294             StreamSP output_stream = reader.GetDebugger().GetAsyncOutputStream();
295             StreamSP error_stream = reader.GetDebugger().GetAsyncErrorStream();
296             cmd_object_expr->EvaluateExpression (cmd_object_expr->m_expr_lines.c_str(), 
297                                                  output_stream.get(), 
298                                                  error_stream.get());
299             output_stream->Flush();
300             error_stream->Flush();
301         }
302         break;
303     }
304
305     return bytes_len;
306 }
307
308 bool
309 CommandObjectExpression::EvaluateExpression 
310 (
311     const char *expr, 
312     Stream *output_stream, 
313     Stream *error_stream,
314     CommandReturnObject *result
315 )
316 {
317     // Don't use m_exe_ctx as this might be called asynchronously
318     // after the command object DoExecute has finished when doing
319     // multi-line expression that use an input reader...
320     ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
321
322     Target *target = exe_ctx.GetTargetPtr();
323     
324     if (!target)
325         target = Host::GetDummyTarget(m_interpreter.GetDebugger()).get();
326     
327     if (target)
328     {
329         lldb::ValueObjectSP result_valobj_sp;
330
331         ExecutionResults exe_results;
332         
333         bool keep_in_memory = true;
334
335         EvaluateExpressionOptions options;
336         options.SetCoerceToId(m_varobj_options.use_objc)
337         .SetUnwindOnError(m_command_options.unwind_on_error)
338         .SetIgnoreBreakpoints (m_command_options.ignore_breakpoints)
339         .SetKeepInMemory(keep_in_memory)
340         .SetUseDynamic(m_varobj_options.use_dynamic)
341         .SetRunOthers(m_command_options.try_all_threads)
342         .SetTimeoutUsec(m_command_options.timeout);
343         
344         exe_results = target->EvaluateExpression (expr, 
345                                                   exe_ctx.GetFramePtr(),
346                                                   result_valobj_sp,
347                                                   options);
348
349         if (result_valobj_sp)
350         {
351             Format format = m_format_options.GetFormat();
352
353             if (result_valobj_sp->GetError().Success())
354             {
355                 if (format != eFormatVoid)
356                 {
357                     if (format != eFormatDefault)
358                         result_valobj_sp->SetFormat (format);
359
360                     ValueObject::DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(true,format));
361
362                     ValueObject::DumpValueObject (*(output_stream),
363                                                   result_valobj_sp.get(),   // Variable object to dump
364                                                   options);
365                     if (result)
366                         result->SetStatus (eReturnStatusSuccessFinishResult);
367                 }
368             }
369             else
370             {
371                 if (result_valobj_sp->GetError().GetError() == ClangUserExpression::kNoResult)
372                 {
373                     if (format != eFormatVoid && m_interpreter.GetDebugger().GetNotifyVoid())
374                     {
375                         error_stream->PutCString("(void)\n");
376                     }
377                     
378                     if (result)
379                         result->SetStatus (eReturnStatusSuccessFinishResult);
380                 }
381                 else
382                 {
383                     const char *error_cstr = result_valobj_sp->GetError().AsCString();
384                     if (error_cstr && error_cstr[0])
385                     {
386                         const size_t error_cstr_len = strlen (error_cstr);
387                         const bool ends_with_newline = error_cstr[error_cstr_len - 1] == '\n';
388                         if (strstr(error_cstr, "error:") != error_cstr)
389                             error_stream->PutCString ("error: ");
390                         error_stream->Write(error_cstr, error_cstr_len);
391                         if (!ends_with_newline)
392                             error_stream->EOL();
393                     }
394                     else
395                     {
396                         error_stream->PutCString ("error: unknown error\n");
397                     }
398                     
399                     if (result)
400                         result->SetStatus (eReturnStatusFailed);
401                 }
402             }
403         }
404     }
405     else
406     {
407         error_stream->Printf ("error: invalid execution context for expression\n");
408         return false;
409     }
410         
411     return true;
412 }
413
414 bool
415 CommandObjectExpression::DoExecute
416 (
417     const char *command,
418     CommandReturnObject &result
419 )
420 {
421     m_option_group.NotifyOptionParsingStarting();
422
423     const char * expr = NULL;
424
425     if (command[0] == '\0')
426     {
427         m_expr_lines.clear();
428         m_expr_line_count = 0;
429         
430         InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
431         if (reader_sp)
432         {
433             Error err (reader_sp->Initialize (CommandObjectExpression::MultiLineExpressionCallback,
434                                               this,                         // baton
435                                               eInputReaderGranularityLine,  // token size, to pass to callback function
436                                               NULL,                         // end token
437                                               NULL,                         // prompt
438                                               true));                       // echo input
439             if (err.Success())
440             {
441                 m_interpreter.GetDebugger().PushInputReader (reader_sp);
442                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
443             }
444             else
445             {
446                 result.AppendError (err.AsCString());
447                 result.SetStatus (eReturnStatusFailed);
448             }
449         }
450         else
451         {
452             result.AppendError("out of memory");
453             result.SetStatus (eReturnStatusFailed);
454         }
455         return result.Succeeded();
456     }
457
458     if (command[0] == '-')
459     {
460         // We have some options and these options MUST end with --.
461         const char *end_options = NULL;
462         const char *s = command;
463         while (s && s[0])
464         {
465             end_options = ::strstr (s, "--");
466             if (end_options)
467             {
468                 end_options += 2; // Get past the "--"
469                 if (::isspace (end_options[0]))
470                 {
471                     expr = end_options;
472                     while (::isspace (*expr))
473                         ++expr;
474                     break;
475                 }
476             }
477             s = end_options;
478         }
479
480         if (end_options)
481         {
482             Args args (command, end_options - command);
483             if (!ParseOptions (args, result))
484                 return false;
485             
486             Error error (m_option_group.NotifyOptionParsingFinished());
487             if (error.Fail())
488             {
489                 result.AppendError (error.AsCString());
490                 result.SetStatus (eReturnStatusFailed);
491                 return false;
492             }
493         }
494     }
495
496     if (expr == NULL)
497         expr = command;
498     
499     if (EvaluateExpression (expr, &(result.GetOutputStream()), &(result.GetErrorStream()), &result))
500         return true;
501
502     result.SetStatus (eReturnStatusFailed);
503     return false;
504 }
505