2010-06-08 16:52:24 +00:00
//===-- CommandObjectExpression.cpp -----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
# include "CommandObjectExpression.h"
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
2010-07-23 00:16:21 +00:00
# include "lldb/Interpreter/Args.h"
2010-06-08 16:52:24 +00:00
# include "lldb/Core/Value.h"
# include "lldb/Core/InputReader.h"
2010-09-30 00:54:27 +00:00
# include "lldb/Core/ValueObjectVariable.h"
2010-06-08 16:52:24 +00:00
# include "lldb/Expression/ClangExpressionVariable.h"
2010-08-27 01:01:44 +00:00
# include "lldb/Expression/ClangUserExpression.h"
2010-07-23 21:47:22 +00:00
# include "lldb/Expression/ClangFunction.h"
2010-06-08 16:52:24 +00:00
# include "lldb/Expression/DWARFExpression.h"
# include "lldb/Host/Host.h"
2010-07-23 00:16:21 +00:00
# include "lldb/Core/Debugger.h"
2010-06-23 01:19:29 +00:00
# include "lldb/Interpreter/CommandInterpreter.h"
2010-06-08 16:52:24 +00:00
# include "lldb/Interpreter/CommandReturnObject.h"
2010-09-30 00:54:27 +00:00
# include "lldb/Target/ObjCLanguageRuntime.h"
2010-06-08 16:52:24 +00:00
# include "lldb/Symbol/ObjectFile.h"
# include "lldb/Symbol/Variable.h"
# include "lldb/Target/Process.h"
# include "lldb/Target/StackFrame.h"
# include "lldb/Target/Target.h"
2011-04-18 08:33:37 +00:00
# include "lldb/Target/Thread.h"
2010-07-23 00:16:21 +00:00
# include "llvm/ADT/StringRef.h"
2010-06-08 16:52:24 +00:00
using namespace lldb ;
using namespace lldb_private ;
2011-04-07 22:46:35 +00:00
CommandObjectExpression : : CommandOptions : : CommandOptions ( CommandInterpreter & interpreter ) :
2011-04-08 22:39:17 +00:00
Options ( interpreter )
2010-06-08 16:52:24 +00:00
{
// Keep only one place to reset the values to their defaults
2011-04-13 00:18:08 +00:00
OptionParsingStarting ( ) ;
2010-06-08 16:52:24 +00:00
}
CommandObjectExpression : : CommandOptions : : ~ CommandOptions ( )
{
}
Error
2011-04-13 00:18:08 +00:00
CommandObjectExpression : : CommandOptions : : SetOptionValue ( uint32_t option_idx , const char * option_arg )
2010-06-08 16:52:24 +00:00
{
Error error ;
char short_option = ( char ) m_getopt_table [ option_idx ] . val ;
switch ( short_option )
{
2010-09-07 22:38:08 +00:00
//case 'l':
//if (language.SetLanguageFromCString (option_arg) == false)
//{
// error.SetErrorStringWithFormat("Invalid language option argument '%s'.\n", option_arg);
//}
//break;
2010-06-08 16:52:24 +00:00
case ' g ' :
debug = true ;
break ;
case ' f ' :
error = Args : : StringToFormat ( option_arg , format ) ;
break ;
2010-09-30 00:54:27 +00:00
case ' o ' :
print_object = true ;
break ;
2010-11-05 19:25:48 +00:00
2011-04-16 00:01:13 +00:00
case ' d ' :
{
bool success ;
bool result ;
result = Args : : StringToBoolean ( option_arg , true , & success ) ;
if ( ! success )
error . SetErrorStringWithFormat ( " Invalid dynamic value setting: \" %s \" . \n " , option_arg ) ;
else
{
if ( result )
use_dynamic = eLazyBoolYes ;
else
use_dynamic = eLazyBoolNo ;
}
}
break ;
2010-11-05 19:25:48 +00:00
case ' u ' :
bool success ;
unwind_on_error = Args : : StringToBoolean ( option_arg , true , & success ) ;
if ( ! success )
error . SetErrorStringWithFormat ( " Could not convert \" %s \" to a boolean value. " , option_arg ) ;
break ;
2010-06-08 16:52:24 +00:00
default :
error . SetErrorStringWithFormat ( " Invalid short option character '%c'. \n " , short_option ) ;
break ;
}
return error ;
}
void
2011-04-13 00:18:08 +00:00
CommandObjectExpression : : CommandOptions : : OptionParsingStarting ( )
2010-06-08 16:52:24 +00:00
{
2010-09-07 22:38:08 +00:00
//language.Clear();
2010-06-08 16:52:24 +00:00
debug = false ;
format = eFormatDefault ;
2010-09-30 00:54:27 +00:00
print_object = false ;
2011-04-16 00:01:13 +00:00
use_dynamic = eLazyBoolCalculate ;
2010-11-05 19:25:48 +00:00
unwind_on_error = true ;
2010-06-08 16:52:24 +00:00
show_types = true ;
show_summary = true ;
}
2011-03-24 21:19:54 +00:00
const OptionDefinition *
2010-06-08 16:52:24 +00:00
CommandObjectExpression : : CommandOptions : : GetDefinitions ( )
{
return g_option_table ;
}
2010-09-18 01:14:36 +00:00
CommandObjectExpression : : CommandObjectExpression ( CommandInterpreter & interpreter ) :
CommandObject ( interpreter ,
" expression " ,
2010-09-30 18:16:58 +00:00
" Evaluate a C/ObjC/C++ expression in the current program context, using variables currently in scope. " ,
2010-10-04 22:28:36 +00:00
NULL ) ,
2011-04-07 22:46:35 +00:00
m_options ( interpreter ) ,
2010-09-30 18:30:25 +00:00
m_expr_line_count ( 0 ) ,
2010-06-08 16:52:24 +00:00
m_expr_lines ( )
{
SetHelpLong (
" Examples: \n \
\n \
expr my_struct->a = my_array[3] \n \
expr -f bin -- (index * 8) + 5 \n \
expr char c[] = \" foo \" ; c[0] \n " ) ;
2010-10-04 22:28:36 +00:00
CommandArgumentEntry arg ;
CommandArgumentData expression_arg ;
// Define the first (and only) variant of this arg.
expression_arg . arg_type = eArgTypeExpression ;
expression_arg . arg_repetition = eArgRepeatPlain ;
// There is only one variant this argument could be; put it into the argument entry.
arg . push_back ( expression_arg ) ;
// Push the data for the first argument into the m_arguments vector.
m_arguments . push_back ( arg ) ;
2010-06-08 16:52:24 +00:00
}
CommandObjectExpression : : ~ CommandObjectExpression ( )
{
}
Options *
CommandObjectExpression : : GetOptions ( )
{
return & m_options ;
}
bool
CommandObjectExpression : : Execute
(
Args & command ,
CommandReturnObject & result
)
{
return false ;
}
size_t
CommandObjectExpression : : MultiLineExpressionCallback
(
void * baton ,
2010-06-23 01:19:29 +00:00
InputReader & reader ,
2010-06-08 16:52:24 +00:00
lldb : : InputReaderAction notification ,
const char * bytes ,
size_t bytes_len
)
{
CommandObjectExpression * cmd_object_expr = ( CommandObjectExpression * ) baton ;
switch ( notification )
{
case eInputReaderActivate :
2010-06-23 01:19:29 +00:00
reader . GetDebugger ( ) . GetOutputStream ( ) . Printf ( " %s \n " , " Enter expressions, then terminate with an empty line to evaluate: " ) ;
2010-06-08 16:52:24 +00:00
// Fall through
case eInputReaderReactivate :
//if (out_fh)
2010-06-23 01:19:29 +00:00
// reader.GetDebugger().GetOutputStream().Printf ("%3u: ", cmd_object_expr->m_expr_line_count);
2010-06-08 16:52:24 +00:00
break ;
case eInputReaderDeactivate :
break ;
case eInputReaderGotToken :
+ + cmd_object_expr - > m_expr_line_count ;
if ( bytes & & bytes_len )
{
cmd_object_expr - > m_expr_lines . append ( bytes , bytes_len + 1 ) ;
}
if ( bytes_len = = 0 )
2010-06-23 01:19:29 +00:00
reader . SetIsDone ( true ) ;
2010-06-08 16:52:24 +00:00
//else if (out_fh && !reader->IsDone())
// ::fprintf (out_fh, "%3u: ", cmd_object_expr->m_expr_line_count);
break ;
2010-11-19 20:47:54 +00:00
case eInputReaderInterrupt :
cmd_object_expr - > m_expr_lines . clear ( ) ;
reader . SetIsDone ( true ) ;
reader . GetDebugger ( ) . GetOutputStream ( ) . Printf ( " %s \n " , " Expression evaluation cancelled. " ) ;
break ;
case eInputReaderEndOfFile :
reader . SetIsDone ( true ) ;
break ;
2010-06-08 16:52:24 +00:00
case eInputReaderDone :
2010-11-19 20:47:54 +00:00
if ( cmd_object_expr - > m_expr_lines . size ( ) > 0 )
2010-06-08 16:52:24 +00:00
{
cmd_object_expr - > EvaluateExpression ( cmd_object_expr - > m_expr_lines . c_str ( ) ,
2010-06-23 01:19:29 +00:00
reader . GetDebugger ( ) . GetOutputStream ( ) ,
reader . GetDebugger ( ) . GetErrorStream ( ) ) ;
2010-06-08 16:52:24 +00:00
}
break ;
}
return bytes_len ;
}
bool
2010-10-05 00:00:42 +00:00
CommandObjectExpression : : EvaluateExpression
(
const char * expr ,
Stream & output_stream ,
Stream & error_stream ,
CommandReturnObject * result
)
2010-06-08 16:52:24 +00:00
{
2010-10-29 00:29:03 +00:00
if ( m_exe_ctx . target )
2010-06-08 16:52:24 +00:00
{
2010-12-14 02:59:59 +00:00
lldb : : ValueObjectSP result_valobj_sp ;
2010-10-06 03:09:11 +00:00
2011-03-24 21:19:54 +00:00
ExecutionResults exe_results ;
2011-01-13 08:53:35 +00:00
bool keep_in_memory = true ;
2011-04-16 00:01:13 +00:00
bool use_dynamic ;
// If use dynamic is not set, get it from the target:
switch ( m_options . use_dynamic )
{
case eLazyBoolCalculate :
{
if ( m_exe_ctx . target - > GetPreferDynamicValue ( ) )
use_dynamic = true ;
else
use_dynamic = false ;
}
break ;
case eLazyBoolYes :
use_dynamic = true ;
break ;
case eLazyBoolNo :
use_dynamic = false ;
break ;
}
2011-01-13 08:53:35 +00:00
2011-04-16 00:01:13 +00:00
exe_results = m_exe_ctx . target - > EvaluateExpression ( expr , m_exe_ctx . frame , m_options . unwind_on_error , use_dynamic , keep_in_memory , result_valobj_sp ) ;
2010-12-14 02:59:59 +00:00
if ( exe_results = = eExecutionInterrupted & & ! m_options . unwind_on_error )
2010-11-30 02:22:11 +00:00
{
2011-04-18 08:33:37 +00:00
uint32_t start_frame = 0 ;
uint32_t num_frames = 1 ;
uint32_t num_frames_with_source = 0 ;
2010-11-30 02:22:11 +00:00
if ( m_exe_ctx . thread )
2011-04-18 08:33:37 +00:00
{
m_exe_ctx . thread - > GetStatus ( result - > GetOutputStream ( ) ,
start_frame ,
num_frames ,
num_frames_with_source ) ;
}
else if ( m_exe_ctx . process )
{
bool only_threads_with_stop_reason = true ;
m_exe_ctx . process - > GetThreadStatus ( result - > GetOutputStream ( ) ,
only_threads_with_stop_reason ,
start_frame ,
num_frames ,
num_frames_with_source ) ;
}
2010-12-14 02:59:59 +00:00
}
if ( result_valobj_sp )
{
if ( result_valobj_sp - > GetError ( ) . Success ( ) )
{
if ( m_options . format ! = eFormatDefault )
result_valobj_sp - > SetFormat ( m_options . format ) ;
ValueObject : : DumpValueObject ( output_stream ,
result_valobj_sp . get ( ) , // Variable object to dump
result_valobj_sp - > GetName ( ) . GetCString ( ) , // Root object name
0 , // Pointer depth to traverse (zero means stop at pointers)
0 , // Current depth, this is the top most, so zero...
UINT32_MAX , // Max depth to go when dumping concrete types, dump everything...
m_options . show_types , // Show types when dumping?
false , // Show locations of variables, no since this is a host address which we don't care to see
m_options . print_object , // Print the objective C object?
2011-04-16 00:01:13 +00:00
use_dynamic ,
2010-12-14 02:59:59 +00:00
true , // Scope is already checked. Const results are always in scope.
false ) ; // Don't flatten output
if ( result )
result - > SetStatus ( eReturnStatusSuccessFinishResult ) ;
}
else
{
error_stream . PutCString ( result_valobj_sp - > GetError ( ) . AsCString ( ) ) ;
if ( result )
result - > SetStatus ( eReturnStatusFailed ) ;
2010-11-30 02:22:11 +00:00
}
}
2010-12-14 02:59:59 +00:00
}
else
{
error_stream . Printf ( " error: invalid execution context for expression \n " ) ;
return false ;
2010-07-23 00:16:21 +00:00
}
2010-08-12 01:56:52 +00:00
2010-07-23 00:16:21 +00:00
return true ;
2010-06-08 16:52:24 +00:00
}
bool
CommandObjectExpression : : ExecuteRawCommandString
(
const char * command ,
CommandReturnObject & result
)
{
2011-04-12 05:54:46 +00:00
m_exe_ctx = m_interpreter . GetExecutionContext ( ) ;
2010-06-08 16:52:24 +00:00
2011-04-13 00:18:08 +00:00
m_options . NotifyOptionParsingStarting ( ) ;
2010-06-08 16:52:24 +00:00
const char * expr = NULL ;
if ( command [ 0 ] = = ' \0 ' )
{
m_expr_lines . clear ( ) ;
m_expr_line_count = 0 ;
2010-09-18 01:14:36 +00:00
InputReaderSP reader_sp ( new InputReader ( m_interpreter . GetDebugger ( ) ) ) ;
2010-06-08 16:52:24 +00:00
if ( reader_sp )
{
Error err ( reader_sp - > Initialize ( CommandObjectExpression : : MultiLineExpressionCallback ,
this , // baton
eInputReaderGranularityLine , // token size, to pass to callback function
2010-06-23 01:19:29 +00:00
NULL , // end token
2010-06-08 16:52:24 +00:00
NULL , // prompt
true ) ) ; // echo input
if ( err . Success ( ) )
{
2010-09-18 01:14:36 +00:00
m_interpreter . GetDebugger ( ) . PushInputReader ( reader_sp ) ;
2010-06-08 16:52:24 +00:00
result . SetStatus ( eReturnStatusSuccessFinishNoResult ) ;
}
else
{
result . AppendError ( err . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
}
else
{
result . AppendError ( " out of memory " ) ;
result . SetStatus ( eReturnStatusFailed ) ;
}
return result . Succeeded ( ) ;
}
if ( command [ 0 ] = = ' - ' )
{
// We have some options and these options MUST end with --.
const char * end_options = NULL ;
const char * s = command ;
while ( s & & s [ 0 ] )
{
end_options = : : strstr ( s , " -- " ) ;
if ( end_options )
{
end_options + = 2 ; // Get past the "--"
if ( : : isspace ( end_options [ 0 ] ) )
{
expr = end_options ;
while ( : : isspace ( * expr ) )
+ + expr ;
break ;
}
}
s = end_options ;
}
if ( end_options )
{
2010-06-23 01:19:29 +00:00
Args args ( command , end_options - command ) ;
2010-09-18 01:14:36 +00:00
if ( ! ParseOptions ( args , result ) )
2010-06-08 16:52:24 +00:00
return false ;
2011-04-13 00:18:08 +00:00
Error error ( m_options . NotifyOptionParsingFinished ( ) ) ;
if ( error . Fail ( ) )
{
result . AppendError ( error . AsCString ( ) ) ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
}
2010-06-08 16:52:24 +00:00
}
}
if ( expr = = NULL )
expr = command ;
2010-06-24 00:16:27 +00:00
2010-10-05 00:31:29 +00:00
if ( EvaluateExpression ( expr , result . GetOutputStream ( ) , result . GetErrorStream ( ) , & result ) )
2010-08-13 00:42:30 +00:00
return true ;
result . SetStatus ( eReturnStatusFailed ) ;
return false ;
2010-06-08 16:52:24 +00:00
}
2011-03-24 21:19:54 +00:00
OptionDefinition
2010-06-08 16:52:24 +00:00
CommandObjectExpression : : CommandOptions : : g_option_table [ ] =
{
2010-09-07 22:38:08 +00:00
//{ LLDB_OPT_SET_ALL, false, "language", 'l', required_argument, NULL, 0, "[c|c++|objc|objc++]", "Sets the language to use when parsing the expression."},
2010-10-01 19:59:14 +00:00
//{ LLDB_OPT_SET_1, false, "format", 'f', required_argument, NULL, 0, "[ [bool|b] | [bin] | [char|c] | [oct|o] | [dec|i|d|u] | [hex|x] | [float|f] | [cstr|s] ]", "Specify the format that the expression output should use."},
{ LLDB_OPT_SET_1 , false , " format " , ' f ' , required_argument , NULL , 0 , eArgTypeExprFormat , " Specify the format that the expression output should use. " } ,
2010-11-05 19:25:48 +00:00
{ LLDB_OPT_SET_2 , false , " object-description " , ' o ' , no_argument , NULL , 0 , eArgTypeNone , " Print the object description of the value resulting from the expression. " } ,
2011-04-16 00:01:13 +00:00
{ LLDB_OPT_SET_2 , false , " dynamic-value " , ' d ' , required_argument , NULL , 0 , eArgTypeBoolean , " Upcast the value resulting from the expression to its dynamic type if available. " } ,
2010-11-05 19:25:48 +00:00
{ LLDB_OPT_SET_ALL , false , " unwind-on-error " , ' u ' , required_argument , NULL , 0 , eArgTypeBoolean , " Clean up program state if the expression causes a crash, breakpoint hit or signal. " } ,
2010-10-01 19:59:14 +00:00
{ LLDB_OPT_SET_ALL , false , " debug " , ' g ' , no_argument , NULL , 0 , eArgTypeNone , " Enable verbose debug logging of the expression parsing and evaluation. " } ,
{ LLDB_OPT_SET_ALL , false , " use-ir " , ' i ' , no_argument , NULL , 0 , eArgTypeNone , " [Temporary] Instructs the expression evaluator to use IR instead of ASTs. " } ,
{ 0 , false , NULL , 0 , 0 , NULL , NULL , eArgTypeNone , NULL }
2010-06-08 16:52:24 +00:00
} ;