2013-08-23 13:46:38 -04:00
//===-- ClangUserExpression.cpp ---------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
# include <stdio.h>
# if HAVE_SYS_TYPES_H
# include <sys / types.h>
# endif
# include <cstdlib>
# include <string>
# include <map>
# include "lldb/Core/ConstString.h"
# include "lldb/Core/Log.h"
2014-11-25 16:00:58 -05:00
# include "lldb/Core/Module.h"
2013-08-23 13:46:38 -04:00
# include "lldb/Core/StreamFile.h"
# include "lldb/Core/StreamString.h"
# include "lldb/Core/ValueObjectConstResult.h"
# include "lldb/Expression/ASTResultSynthesizer.h"
# include "lldb/Expression/ClangExpressionDeclMap.h"
# include "lldb/Expression/ClangExpressionParser.h"
# include "lldb/Expression/ClangFunction.h"
# include "lldb/Expression/ClangUserExpression.h"
# include "lldb/Expression/ExpressionSourceCode.h"
# include "lldb/Expression/IRExecutionUnit.h"
# include "lldb/Expression/IRInterpreter.h"
# include "lldb/Expression/Materializer.h"
2014-11-25 16:00:58 -05:00
# include "lldb/Host/HostInfo.h"
2013-08-23 13:46:38 -04:00
# include "lldb/Symbol/Block.h"
# include "lldb/Symbol/ClangASTContext.h"
# include "lldb/Symbol/Function.h"
2014-11-25 16:00:58 -05:00
# include "lldb/Symbol/ObjectFile.h"
# include "lldb/Symbol/SymbolVendor.h"
2013-08-23 13:46:38 -04:00
# include "lldb/Symbol/Type.h"
# include "lldb/Symbol/ClangExternalASTSourceCommon.h"
# include "lldb/Symbol/VariableList.h"
# include "lldb/Target/ExecutionContext.h"
# include "lldb/Target/Process.h"
# include "lldb/Target/StackFrame.h"
# include "lldb/Target/Target.h"
# include "lldb/Target/ThreadPlan.h"
# include "lldb/Target/ThreadPlanCallUserExpression.h"
# include "clang/AST/DeclCXX.h"
# include "clang/AST/DeclObjC.h"
using namespace lldb_private ;
ClangUserExpression : : ClangUserExpression ( const char * expr ,
const char * expr_prefix ,
lldb : : LanguageType language ,
ResultType desired_type ) :
ClangExpression ( ) ,
m_stack_frame_bottom ( LLDB_INVALID_ADDRESS ) ,
m_stack_frame_top ( LLDB_INVALID_ADDRESS ) ,
m_expr_text ( expr ) ,
m_expr_prefix ( expr_prefix ? expr_prefix : " " ) ,
m_language ( language ) ,
m_transformed_text ( ) ,
m_desired_type ( desired_type ) ,
2014-11-25 16:00:58 -05:00
m_expr_decl_map ( ) ,
m_execution_unit_sp ( ) ,
m_materializer_ap ( ) ,
m_result_synthesizer ( ) ,
m_jit_module_wp ( ) ,
2013-08-23 13:46:38 -04:00
m_enforce_valid_object ( true ) ,
m_cplusplus ( false ) ,
m_objectivec ( false ) ,
m_static_method ( false ) ,
m_needs_object_ptr ( false ) ,
m_const_object ( false ) ,
m_target ( NULL ) ,
m_can_interpret ( false ) ,
m_materialized_address ( LLDB_INVALID_ADDRESS )
{
switch ( m_language )
{
case lldb : : eLanguageTypeC_plus_plus :
m_allow_cxx = true ;
break ;
case lldb : : eLanguageTypeObjC :
m_allow_objc = true ;
break ;
case lldb : : eLanguageTypeObjC_plus_plus :
default :
m_allow_cxx = true ;
m_allow_objc = true ;
break ;
}
}
ClangUserExpression : : ~ ClangUserExpression ( )
{
2014-11-25 16:00:58 -05:00
if ( m_target )
{
lldb : : ModuleSP jit_module_sp ( m_jit_module_wp . lock ( ) ) ;
if ( jit_module_sp )
m_target - > GetImages ( ) . Remove ( jit_module_sp ) ;
}
2013-08-23 13:46:38 -04:00
}
clang : : ASTConsumer *
ClangUserExpression : : ASTTransformer ( clang : : ASTConsumer * passthrough )
2013-11-06 11:48:53 -05:00
{
m_result_synthesizer . reset ( new ASTResultSynthesizer ( passthrough ,
* m_target ) ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
return m_result_synthesizer . get ( ) ;
}
void
ClangUserExpression : : ScanContext ( ExecutionContext & exe_ctx , Error & err )
{
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
if ( log )
log - > Printf ( " ClangUserExpression::ScanContext() " ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
m_target = exe_ctx . GetTargetPtr ( ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! ( m_allow_cxx | | m_allow_objc ) )
{
if ( log )
log - > Printf ( " [CUE::SC] Settings inhibit C++ and Objective-C " ) ;
return ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
StackFrame * frame = exe_ctx . GetFramePtr ( ) ;
if ( frame = = NULL )
{
if ( log )
log - > Printf ( " [CUE::SC] Null stack frame " ) ;
return ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
SymbolContext sym_ctx = frame - > GetSymbolContext ( lldb : : eSymbolContextFunction | lldb : : eSymbolContextBlock ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! sym_ctx . function )
{
if ( log )
log - > Printf ( " [CUE::SC] Null function " ) ;
return ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
// Find the block that defines the function represented by "sym_ctx"
Block * function_block = sym_ctx . GetFunctionBlock ( ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! function_block )
{
if ( log )
log - > Printf ( " [CUE::SC] Null function block " ) ;
return ;
}
clang : : DeclContext * decl_context = function_block - > GetClangDeclContext ( ) ;
if ( ! decl_context )
{
if ( log )
log - > Printf ( " [CUE::SC] Null decl context " ) ;
return ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( clang : : CXXMethodDecl * method_decl = llvm : : dyn_cast < clang : : CXXMethodDecl > ( decl_context ) )
{
if ( m_allow_cxx & & method_decl - > isInstance ( ) )
{
if ( m_enforce_valid_object )
{
lldb : : VariableListSP variable_list_sp ( function_block - > GetBlockVariableList ( true ) ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
const char * thisErrorString = " Stopped in a C++ method, but 'this' isn't available; pretending we are in a generic context " ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! variable_list_sp )
{
err . SetErrorString ( thisErrorString ) ;
return ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
lldb : : VariableSP this_var_sp ( variable_list_sp - > FindVariable ( ConstString ( " this " ) ) ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! this_var_sp | |
2014-11-25 16:00:58 -05:00
! this_var_sp - > IsInScope ( frame ) | |
2013-08-23 13:46:38 -04:00
! this_var_sp - > LocationIsValidForFrame ( frame ) )
{
err . SetErrorString ( thisErrorString ) ;
return ;
}
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
m_cplusplus = true ;
m_needs_object_ptr = true ;
}
}
else if ( clang : : ObjCMethodDecl * method_decl = llvm : : dyn_cast < clang : : ObjCMethodDecl > ( decl_context ) )
2014-11-25 16:00:58 -05:00
{
2013-08-23 13:46:38 -04:00
if ( m_allow_objc )
{
if ( m_enforce_valid_object )
{
lldb : : VariableListSP variable_list_sp ( function_block - > GetBlockVariableList ( true ) ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
const char * selfErrorString = " Stopped in an Objective-C method, but 'self' isn't available; pretending we are in a generic context " ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! variable_list_sp )
{
err . SetErrorString ( selfErrorString ) ;
return ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
lldb : : VariableSP self_variable_sp = variable_list_sp - > FindVariable ( ConstString ( " self " ) ) ;
2014-11-25 16:00:58 -05:00
if ( ! self_variable_sp | |
! self_variable_sp - > IsInScope ( frame ) | |
2013-08-23 13:46:38 -04:00
! self_variable_sp - > LocationIsValidForFrame ( frame ) )
{
err . SetErrorString ( selfErrorString ) ;
return ;
}
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
m_objectivec = true ;
m_needs_object_ptr = true ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! method_decl - > isInstanceMethod ( ) )
m_static_method = true ;
}
}
else if ( clang : : FunctionDecl * function_decl = llvm : : dyn_cast < clang : : FunctionDecl > ( decl_context ) )
{
// We might also have a function that said in the debug information that it captured an
// object pointer. The best way to deal with getting to the ivars at present it by pretending
// that this is a method of a class in whatever runtime the debug info says the object pointer
// belongs to. Do that here.
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
ClangASTMetadata * metadata = ClangASTContext : : GetMetadata ( & decl_context - > getParentASTContext ( ) , function_decl ) ;
if ( metadata & & metadata - > HasObjectPtr ( ) )
{
lldb : : LanguageType language = metadata - > GetObjectPtrLanguage ( ) ;
if ( language = = lldb : : eLanguageTypeC_plus_plus )
{
if ( m_enforce_valid_object )
{
lldb : : VariableListSP variable_list_sp ( function_block - > GetBlockVariableList ( true ) ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
const char * thisErrorString = " Stopped in a context claiming to capture a C++ object pointer, but 'this' isn't available; pretending we are in a generic context " ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! variable_list_sp )
{
err . SetErrorString ( thisErrorString ) ;
return ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
lldb : : VariableSP this_var_sp ( variable_list_sp - > FindVariable ( ConstString ( " this " ) ) ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! this_var_sp | |
! this_var_sp - > IsInScope ( frame ) | |
! this_var_sp - > LocationIsValidForFrame ( frame ) )
{
err . SetErrorString ( thisErrorString ) ;
return ;
}
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
m_cplusplus = true ;
m_needs_object_ptr = true ;
}
else if ( language = = lldb : : eLanguageTypeObjC )
{
if ( m_enforce_valid_object )
{
lldb : : VariableListSP variable_list_sp ( function_block - > GetBlockVariableList ( true ) ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
const char * selfErrorString = " Stopped in a context claiming to capture an Objective-C object pointer, but 'self' isn't available; pretending we are in a generic context " ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! variable_list_sp )
{
err . SetErrorString ( selfErrorString ) ;
return ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
lldb : : VariableSP self_variable_sp = variable_list_sp - > FindVariable ( ConstString ( " self " ) ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! self_variable_sp | |
! self_variable_sp - > IsInScope ( frame ) | |
! self_variable_sp - > LocationIsValidForFrame ( frame ) )
{
err . SetErrorString ( selfErrorString ) ;
return ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
Type * self_type = self_variable_sp - > GetType ( ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! self_type )
{
err . SetErrorString ( selfErrorString ) ;
return ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
ClangASTType self_clang_type = self_type - > GetClangForwardType ( ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! self_clang_type )
{
err . SetErrorString ( selfErrorString ) ;
return ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( self_clang_type . IsObjCClassType ( ) )
{
return ;
}
else if ( self_clang_type . IsObjCObjectPointerType ( ) )
{
m_objectivec = true ;
m_needs_object_ptr = true ;
}
else
{
err . SetErrorString ( selfErrorString ) ;
return ;
}
}
else
{
m_objectivec = true ;
m_needs_object_ptr = true ;
}
}
}
}
}
void
ClangUserExpression : : InstallContext ( ExecutionContext & exe_ctx )
{
m_process_wp = exe_ctx . GetProcessSP ( ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
lldb : : StackFrameSP frame_sp = exe_ctx . GetFrameSP ( ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( frame_sp )
m_address = frame_sp - > GetFrameCodeAddress ( ) ;
}
bool
ClangUserExpression : : LockAndCheckContext ( ExecutionContext & exe_ctx ,
lldb : : TargetSP & target_sp ,
lldb : : ProcessSP & process_sp ,
lldb : : StackFrameSP & frame_sp )
{
lldb : : ProcessSP expected_process_sp = m_process_wp . lock ( ) ;
process_sp = exe_ctx . GetProcessSP ( ) ;
if ( process_sp ! = expected_process_sp )
return false ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
process_sp = exe_ctx . GetProcessSP ( ) ;
target_sp = exe_ctx . GetTargetSP ( ) ;
frame_sp = exe_ctx . GetFrameSP ( ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( m_address . IsValid ( ) )
{
if ( ! frame_sp )
return false ;
else
return ( 0 = = Address : : CompareLoadAddress ( m_address , frame_sp - > GetFrameCodeAddress ( ) , target_sp . get ( ) ) ) ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
return true ;
}
bool
ClangUserExpression : : MatchesContext ( ExecutionContext & exe_ctx )
{
lldb : : TargetSP target_sp ;
lldb : : ProcessSP process_sp ;
lldb : : StackFrameSP frame_sp ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
return LockAndCheckContext ( exe_ctx , target_sp , process_sp , frame_sp ) ;
}
// This is a really nasty hack, meant to fix Objective-C expressions of the form
// (int)[myArray count]. Right now, because the type information for count is
// not available, [myArray count] returns id, which can't be directly cast to
// int without causing a clang error.
static void
ApplyObjcCastHack ( std : : string & expr )
{
# define OBJC_CAST_HACK_FROM "(int)["
# define OBJC_CAST_HACK_TO "(int)(long long)["
size_t from_offset ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
while ( ( from_offset = expr . find ( OBJC_CAST_HACK_FROM ) ) ! = expr . npos )
expr . replace ( from_offset , sizeof ( OBJC_CAST_HACK_FROM ) - 1 , OBJC_CAST_HACK_TO ) ;
# undef OBJC_CAST_HACK_TO
# undef OBJC_CAST_HACK_FROM
}
// Another hack, meant to allow use of unichar despite it not being available in
// the type information. Although we could special-case it in type lookup,
// hopefully we'll figure out a way to #include the same environment as is
// present in the original source file rather than try to hack specific type
// definitions in as needed.
2014-11-25 16:00:58 -05:00
//static void
//ApplyUnicharHack(std::string &expr)
//{
//#define UNICHAR_HACK_FROM "unichar"
//#define UNICHAR_HACK_TO "unsigned short"
//
// size_t from_offset;
//
// while ((from_offset = expr.find(UNICHAR_HACK_FROM)) != expr.npos)
// expr.replace(from_offset, sizeof(UNICHAR_HACK_FROM) - 1, UNICHAR_HACK_TO);
//
//#undef UNICHAR_HACK_TO
//#undef UNICHAR_HACK_FROM
//}
2013-08-23 13:46:38 -04:00
bool
2014-11-25 16:00:58 -05:00
ClangUserExpression : : Parse ( Stream & error_stream ,
2013-08-23 13:46:38 -04:00
ExecutionContext & exe_ctx ,
lldb_private : : ExecutionPolicy execution_policy ,
2014-11-25 16:00:58 -05:00
bool keep_result_in_memory ,
bool generate_debug_info )
2013-08-23 13:46:38 -04:00
{
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
Error err ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
InstallContext ( exe_ctx ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
ScanContext ( exe_ctx , err ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! err . Success ( ) )
{
error_stream . Printf ( " warning: %s \n " , err . AsCString ( ) ) ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
StreamString m_transformed_stream ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
////////////////////////////////////
// Generate the expression
//
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
ApplyObjcCastHack ( m_expr_text ) ;
//ApplyUnicharHack(m_expr_text);
std : : unique_ptr < ExpressionSourceCode > source_code ( ExpressionSourceCode : : CreateWrapped ( m_expr_prefix . c_str ( ) , m_expr_text . c_str ( ) ) ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
lldb : : LanguageType lang_type ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( m_cplusplus )
lang_type = lldb : : eLanguageTypeC_plus_plus ;
else if ( m_objectivec )
lang_type = lldb : : eLanguageTypeObjC ;
else
lang_type = lldb : : eLanguageTypeC ;
2014-11-25 16:00:58 -05:00
if ( ! source_code - > GetText ( m_transformed_text , lang_type , m_const_object , m_static_method , exe_ctx ) )
2013-08-23 13:46:38 -04:00
{
error_stream . PutCString ( " error: couldn't construct expression body " ) ;
return false ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( log )
log - > Printf ( " Parsing the following code: \n %s " , m_transformed_text . c_str ( ) ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
////////////////////////////////////
// Set up the target and compiler
//
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
Target * target = exe_ctx . GetTargetPtr ( ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! target )
{
error_stream . PutCString ( " error: invalid target \n " ) ;
return false ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
//////////////////////////
// Parse the expression
//
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
m_materializer_ap . reset ( new Materializer ( ) ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
m_expr_decl_map . reset ( new ClangExpressionDeclMap ( keep_result_in_memory , exe_ctx ) ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
class OnExit
{
public :
typedef std : : function < void ( void ) > Callback ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
OnExit ( Callback const & callback ) :
m_callback ( callback )
{
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
~ OnExit ( )
{
m_callback ( ) ;
}
private :
Callback m_callback ;
} ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
OnExit on_exit ( [ this ] ( ) { m_expr_decl_map . reset ( ) ; } ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! m_expr_decl_map - > WillParse ( exe_ctx , m_materializer_ap . get ( ) ) )
{
error_stream . PutCString ( " error: current process state is unsuitable for expression parsing \n " ) ;
2014-11-25 16:00:58 -05:00
2013-11-06 11:48:53 -05:00
m_expr_decl_map . reset ( ) ; // We are being careful here in the case of breakpoint conditions.
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
return false ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
Process * process = exe_ctx . GetProcessPtr ( ) ;
ExecutionContextScope * exe_scope = process ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! exe_scope )
exe_scope = exe_ctx . GetTargetPtr ( ) ;
2014-11-25 16:00:58 -05:00
ClangExpressionParser parser ( exe_scope , * this , generate_debug_info ) ;
2013-08-23 13:46:38 -04:00
unsigned num_errors = parser . Parse ( error_stream ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( num_errors )
{
error_stream . Printf ( " error: %d errors parsing expression \n " , num_errors ) ;
2014-11-25 16:00:58 -05:00
2013-11-06 11:48:53 -05:00
m_expr_decl_map . reset ( ) ; // We are being careful here in the case of breakpoint conditions.
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
return false ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
//////////////////////////////////////////////////////////////////////////////////////////
// Prepare the output of the parser for execution, evaluating it statically if possible
//
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
Error jit_error = parser . PrepareForExecution ( m_jit_start_addr ,
m_jit_end_addr ,
2014-11-25 16:00:58 -05:00
m_execution_unit_sp ,
2013-08-23 13:46:38 -04:00
exe_ctx ,
m_can_interpret ,
execution_policy ) ;
2014-11-25 16:00:58 -05:00
if ( generate_debug_info )
{
lldb : : ModuleSP jit_module_sp ( m_execution_unit_sp - > GetJITModule ( ) ) ;
if ( jit_module_sp )
{
ConstString const_func_name ( FunctionName ( ) ) ;
FileSpec jit_file ;
jit_file . GetFilename ( ) = const_func_name ;
jit_module_sp - > SetFileSpecAndObjectName ( jit_file , ConstString ( ) ) ;
m_jit_module_wp = jit_module_sp ;
target - > GetImages ( ) . Append ( jit_module_sp ) ;
}
// lldb_private::ObjectFile *jit_obj_file = jit_module_sp->GetObjectFile();
// StreamFile strm (stdout, false);
// if (jit_obj_file)
// {
// jit_obj_file->GetSectionList();
// jit_obj_file->GetSymtab();
// jit_obj_file->Dump(&strm);
// }
// lldb_private::SymbolVendor *jit_sym_vendor = jit_module_sp->GetSymbolVendor();
// if (jit_sym_vendor)
// {
// lldb_private::SymbolContextList sc_list;
// jit_sym_vendor->FindFunctions(const_func_name, NULL, lldb::eFunctionNameTypeFull, true, false, sc_list);
// sc_list.Dump(&strm, target);
// jit_sym_vendor->Dump(&strm);
// }
}
2013-11-06 11:48:53 -05:00
m_expr_decl_map . reset ( ) ; // Make this go away since we don't need any of its state after parsing. This also gets rid of any ClangASTImporter::Minions.
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( jit_error . Success ( ) )
{
if ( process & & m_jit_start_addr ! = LLDB_INVALID_ADDRESS )
m_jit_process_wp = lldb : : ProcessWP ( process - > shared_from_this ( ) ) ;
return true ;
}
else
{
const char * error_cstr = jit_error . AsCString ( ) ;
if ( error_cstr & & error_cstr [ 0 ] )
error_stream . Printf ( " error: %s \n " , error_cstr ) ;
else
error_stream . Printf ( " error: expression can't be interpreted or run \n " ) ;
return false ;
}
}
static lldb : : addr_t
GetObjectPointer ( lldb : : StackFrameSP frame_sp ,
ConstString & object_name ,
Error & err )
{
err . Clear ( ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! frame_sp )
{
err . SetErrorStringWithFormat ( " Couldn't load '%s' because the context is incomplete " , object_name . AsCString ( ) ) ;
return LLDB_INVALID_ADDRESS ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
lldb : : VariableSP var_sp ;
lldb : : ValueObjectSP valobj_sp ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
valobj_sp = frame_sp - > GetValueForVariableExpressionPath ( object_name . AsCString ( ) ,
lldb : : eNoDynamicValues ,
2015-02-06 16:38:51 -05:00
StackFrame : : eExpressionPathOptionCheckPtrVsMember |
StackFrame : : eExpressionPathOptionsNoFragileObjcIvar |
StackFrame : : eExpressionPathOptionsNoSyntheticChildren |
2013-08-23 13:46:38 -04:00
StackFrame : : eExpressionPathOptionsNoSyntheticArrayRange ,
var_sp ,
err ) ;
2014-11-25 16:00:58 -05:00
2015-02-06 16:38:51 -05:00
if ( ! err . Success ( ) | | ! valobj_sp . get ( ) )
2013-08-23 13:46:38 -04:00
return LLDB_INVALID_ADDRESS ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
lldb : : addr_t ret = valobj_sp - > GetValueAsUnsigned ( LLDB_INVALID_ADDRESS ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ret = = LLDB_INVALID_ADDRESS )
{
err . SetErrorStringWithFormat ( " Couldn't load '%s' because its value couldn't be evaluated " , object_name . AsCString ( ) ) ;
return LLDB_INVALID_ADDRESS ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
return ret ;
}
bool
ClangUserExpression : : PrepareToExecuteJITExpression ( Stream & error_stream ,
ExecutionContext & exe_ctx ,
lldb : : addr_t & struct_address ,
lldb : : addr_t & object_ptr ,
lldb : : addr_t & cmd_ptr )
{
lldb : : TargetSP target ;
lldb : : ProcessSP process ;
lldb : : StackFrameSP frame ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! LockAndCheckContext ( exe_ctx ,
target ,
2014-11-25 16:00:58 -05:00
process ,
2013-08-23 13:46:38 -04:00
frame ) )
{
error_stream . Printf ( " The context has changed before we could JIT the expression! \n " ) ;
return false ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( m_jit_start_addr ! = LLDB_INVALID_ADDRESS | | m_can_interpret )
2014-11-25 16:00:58 -05:00
{
2013-08-23 13:46:38 -04:00
if ( m_needs_object_ptr )
{
ConstString object_name ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( m_cplusplus )
{
object_name . SetCString ( " this " ) ;
}
else if ( m_objectivec )
{
object_name . SetCString ( " self " ) ;
}
else
{
error_stream . Printf ( " Need object pointer but don't know the language \n " ) ;
return false ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
Error object_ptr_error ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
object_ptr = GetObjectPointer ( frame , object_name , object_ptr_error ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! object_ptr_error . Success ( ) )
{
error_stream . Printf ( " warning: couldn't get required object pointer (substituting NULL): %s \n " , object_ptr_error . AsCString ( ) ) ;
object_ptr = 0 ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( m_objectivec )
{
ConstString cmd_name ( " _cmd " ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
cmd_ptr = GetObjectPointer ( frame , cmd_name , object_ptr_error ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! object_ptr_error . Success ( ) )
{
error_stream . Printf ( " warning: couldn't get cmd pointer (substituting NULL): %s \n " , object_ptr_error . AsCString ( ) ) ;
cmd_ptr = 0 ;
}
}
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( m_materialized_address = = LLDB_INVALID_ADDRESS )
{
Error alloc_error ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
IRMemoryMap : : AllocationPolicy policy = m_can_interpret ? IRMemoryMap : : eAllocationPolicyHostOnly : IRMemoryMap : : eAllocationPolicyMirror ;
2014-11-25 16:00:58 -05:00
m_materialized_address = m_execution_unit_sp - > Malloc ( m_materializer_ap - > GetStructByteSize ( ) ,
2013-08-23 13:46:38 -04:00
m_materializer_ap - > GetStructAlignment ( ) ,
lldb : : ePermissionsReadable | lldb : : ePermissionsWritable ,
policy ,
alloc_error ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! alloc_error . Success ( ) )
{
error_stream . Printf ( " Couldn't allocate space for materialized struct: %s \n " , alloc_error . AsCString ( ) ) ;
return false ;
}
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
struct_address = m_materialized_address ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( m_can_interpret & & m_stack_frame_bottom = = LLDB_INVALID_ADDRESS )
{
Error alloc_error ;
const size_t stack_frame_size = 512 * 1024 ;
2014-11-25 16:00:58 -05:00
m_stack_frame_bottom = m_execution_unit_sp - > Malloc ( stack_frame_size ,
2013-08-23 13:46:38 -04:00
8 ,
lldb : : ePermissionsReadable | lldb : : ePermissionsWritable ,
IRMemoryMap : : eAllocationPolicyHostOnly ,
alloc_error ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
m_stack_frame_top = m_stack_frame_bottom + stack_frame_size ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! alloc_error . Success ( ) )
{
error_stream . Printf ( " Couldn't allocate space for the stack frame: %s \n " , alloc_error . AsCString ( ) ) ;
return false ;
}
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
Error materialize_error ;
2014-11-25 16:00:58 -05:00
m_dematerializer_sp = m_materializer_ap - > Materialize ( frame , * m_execution_unit_sp , struct_address , materialize_error ) ;
2013-08-23 13:46:38 -04:00
if ( ! materialize_error . Success ( ) )
{
2014-11-25 16:00:58 -05:00
error_stream . Printf ( " Couldn't materialize: %s \n " , materialize_error . AsCString ( ) ) ;
2013-08-23 13:46:38 -04:00
return false ;
}
}
return true ;
}
bool
ClangUserExpression : : FinalizeJITExecution ( Stream & error_stream ,
ExecutionContext & exe_ctx ,
lldb : : ClangExpressionVariableSP & result ,
lldb : : addr_t function_stack_bottom ,
lldb : : addr_t function_stack_top )
{
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( log )
log - > Printf ( " -- [ClangUserExpression::FinalizeJITExecution] Dematerializing after execution -- " ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! m_dematerializer_sp )
{
error_stream . Printf ( " Couldn't apply expression side effects : no dematerializer is present " ) ;
return false ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
Error dematerialize_error ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
m_dematerializer_sp - > Dematerialize ( dematerialize_error , result , function_stack_bottom , function_stack_top ) ;
if ( ! dematerialize_error . Success ( ) )
{
error_stream . Printf ( " Couldn't apply expression side effects : %s \n " , dematerialize_error . AsCString ( " unknown error " ) ) ;
return false ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( result )
result - > TransferAddress ( ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
m_dematerializer_sp . reset ( ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
return true ;
2014-11-25 16:00:58 -05:00
}
2013-08-23 13:46:38 -04:00
2014-11-25 16:00:58 -05:00
lldb : : ExpressionResults
2013-08-23 13:46:38 -04:00
ClangUserExpression : : Execute ( Stream & error_stream ,
ExecutionContext & exe_ctx ,
2013-11-06 11:48:53 -05:00
const EvaluateExpressionOptions & options ,
2013-08-23 13:46:38 -04:00
ClangUserExpression : : ClangUserExpressionSP & shared_ptr_to_me ,
2013-11-06 11:48:53 -05:00
lldb : : ClangExpressionVariableSP & result )
2013-08-23 13:46:38 -04:00
{
// The expression log is quite verbose, and if you're just tracking the execution of the
// expression, it's quite convenient to have these logs come out with the STEP log as well.
Log * log ( lldb_private : : GetLogIfAnyCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP ) ) ;
if ( m_jit_start_addr ! = LLDB_INVALID_ADDRESS | | m_can_interpret )
{
lldb : : addr_t struct_address = LLDB_INVALID_ADDRESS ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
lldb : : addr_t object_ptr = 0 ;
lldb : : addr_t cmd_ptr = 0 ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! PrepareToExecuteJITExpression ( error_stream , exe_ctx , struct_address , object_ptr , cmd_ptr ) )
{
error_stream . Printf ( " Errored out in %s, couldn't PrepareToExecuteJITExpression " , __FUNCTION__ ) ;
2014-11-25 16:00:58 -05:00
return lldb : : eExpressionSetupError ;
2013-08-23 13:46:38 -04:00
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
lldb : : addr_t function_stack_bottom = LLDB_INVALID_ADDRESS ;
lldb : : addr_t function_stack_top = LLDB_INVALID_ADDRESS ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( m_can_interpret )
2014-11-25 16:00:58 -05:00
{
llvm : : Module * module = m_execution_unit_sp - > GetModule ( ) ;
llvm : : Function * function = m_execution_unit_sp - > GetFunction ( ) ;
2013-08-23 13:46:38 -04:00
if ( ! module | | ! function )
{
error_stream . Printf ( " Supposed to interpret, but nothing is there " ) ;
2014-11-25 16:00:58 -05:00
return lldb : : eExpressionSetupError ;
2013-08-23 13:46:38 -04:00
}
Error interpreter_error ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
llvm : : SmallVector < lldb : : addr_t , 3 > args ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( m_needs_object_ptr )
{
args . push_back ( object_ptr ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( m_objectivec )
args . push_back ( cmd_ptr ) ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
args . push_back ( struct_address ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
function_stack_bottom = m_stack_frame_bottom ;
function_stack_top = m_stack_frame_top ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
IRInterpreter : : Interpret ( * module ,
* function ,
args ,
2014-11-25 16:00:58 -05:00
* m_execution_unit_sp . get ( ) ,
2013-08-23 13:46:38 -04:00
interpreter_error ,
function_stack_bottom ,
function_stack_top ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! interpreter_error . Success ( ) )
{
error_stream . Printf ( " Supposed to interpret, but failed: %s " , interpreter_error . AsCString ( ) ) ;
2014-11-25 16:00:58 -05:00
return lldb : : eExpressionDiscarded ;
2013-08-23 13:46:38 -04:00
}
}
else
{
2014-11-25 16:00:58 -05:00
if ( ! exe_ctx . HasThreadScope ( ) )
{
error_stream . Printf ( " ClangUserExpression::Execute called with no thread selected. " ) ;
return lldb : : eExpressionSetupError ;
}
2013-08-23 13:46:38 -04:00
Address wrapper_address ( m_jit_start_addr ) ;
2014-11-25 16:00:58 -05:00
2013-12-03 13:51:59 -05:00
llvm : : SmallVector < lldb : : addr_t , 3 > args ;
2014-11-25 16:00:58 -05:00
2013-12-03 13:51:59 -05:00
if ( m_needs_object_ptr ) {
args . push_back ( object_ptr ) ;
if ( m_objectivec )
args . push_back ( cmd_ptr ) ;
}
2014-11-25 16:00:58 -05:00
2013-12-03 13:51:59 -05:00
args . push_back ( struct_address ) ;
2014-11-25 16:00:58 -05:00
2015-02-06 16:38:51 -05:00
lldb : : ThreadPlanSP call_plan_sp ( new ThreadPlanCallUserExpression ( exe_ctx . GetThreadRef ( ) ,
wrapper_address ,
args ,
options ,
shared_ptr_to_me ) ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! call_plan_sp | | ! call_plan_sp - > ValidatePlan ( & error_stream ) )
2014-11-25 16:00:58 -05:00
return lldb : : eExpressionSetupError ;
2013-08-23 13:46:38 -04:00
2015-02-06 16:38:51 -05:00
ThreadPlanCallUserExpression * user_expression_plan = static_cast < ThreadPlanCallUserExpression * > ( call_plan_sp . get ( ) ) ;
2014-11-25 16:00:58 -05:00
lldb : : addr_t function_stack_pointer = user_expression_plan - > GetFunctionStackPointer ( ) ;
function_stack_bottom = function_stack_pointer - HostInfo : : GetPageSize ( ) ;
2013-08-23 13:46:38 -04:00
function_stack_top = function_stack_pointer ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( log )
log - > Printf ( " -- [ClangUserExpression::Execute] Execution of expression begins -- " ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( exe_ctx . GetProcessPtr ( ) )
exe_ctx . GetProcessPtr ( ) - > SetRunningUserExpression ( true ) ;
2014-11-25 16:00:58 -05:00
lldb : : ExpressionResults execution_result = exe_ctx . GetProcessRef ( ) . RunThreadPlan ( exe_ctx ,
2013-12-03 13:51:59 -05:00
call_plan_sp ,
options ,
2013-08-23 13:46:38 -04:00
error_stream ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( exe_ctx . GetProcessPtr ( ) )
exe_ctx . GetProcessPtr ( ) - > SetRunningUserExpression ( false ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( log )
log - > Printf ( " -- [ClangUserExpression::Execute] Execution of expression completed -- " ) ;
2014-11-25 16:00:58 -05:00
if ( execution_result = = lldb : : eExpressionInterrupted | | execution_result = = lldb : : eExpressionHitBreakpoint )
2013-08-23 13:46:38 -04:00
{
const char * error_desc = NULL ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( call_plan_sp )
{
lldb : : StopInfoSP real_stop_info_sp = call_plan_sp - > GetRealStopInfo ( ) ;
if ( real_stop_info_sp )
error_desc = real_stop_info_sp - > GetDescription ( ) ;
}
if ( error_desc )
error_stream . Printf ( " Execution was interrupted, reason: %s. " , error_desc ) ;
else
2013-12-03 13:51:59 -05:00
error_stream . PutCString ( " Execution was interrupted. " ) ;
2014-11-25 16:00:58 -05:00
if ( ( execution_result = = lldb : : eExpressionInterrupted & & options . DoesUnwindOnError ( ) )
| | ( execution_result = = lldb : : eExpressionHitBreakpoint & & options . DoesIgnoreBreakpoints ( ) ) )
2013-12-03 13:51:59 -05:00
error_stream . PutCString ( " \n The process has been returned to the state before expression evaluation. " ) ;
2013-08-23 13:46:38 -04:00
else
2014-11-25 16:00:58 -05:00
{
if ( execution_result = = lldb : : eExpressionHitBreakpoint )
user_expression_plan - > TransferExpressionOwnership ( ) ;
error_stream . PutCString ( " \n The process has been left at the point where it was interrupted, "
" use \" thread return -x \" to return to the state before expression evaluation. " ) ;
}
2013-08-23 13:46:38 -04:00
return execution_result ;
}
2014-11-25 16:00:58 -05:00
else if ( execution_result = = lldb : : eExpressionStoppedForDebug )
2013-12-03 13:51:59 -05:00
{
2014-11-25 16:00:58 -05:00
error_stream . PutCString ( " Execution was halted at the first instruction of the expression "
" function because \" debug \" was requested. \n "
2013-12-03 13:51:59 -05:00
" Use \" thread return -x \" to return to the state before expression evaluation. " ) ;
return execution_result ;
}
2014-11-25 16:00:58 -05:00
else if ( execution_result ! = lldb : : eExpressionCompleted )
2013-08-23 13:46:38 -04:00
{
error_stream . Printf ( " Couldn't execute function; result was %s \n " , Process : : ExecutionResultAsCString ( execution_result ) ) ;
return execution_result ;
}
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( FinalizeJITExecution ( error_stream , exe_ctx , result , function_stack_bottom , function_stack_top ) )
{
2014-11-25 16:00:58 -05:00
return lldb : : eExpressionCompleted ;
2013-08-23 13:46:38 -04:00
}
else
{
2014-11-25 16:00:58 -05:00
return lldb : : eExpressionResultUnavailable ;
2013-08-23 13:46:38 -04:00
}
}
else
{
error_stream . Printf ( " Expression can't be run, because there is no JIT compiled function " ) ;
2014-11-25 16:00:58 -05:00
return lldb : : eExpressionSetupError ;
2013-08-23 13:46:38 -04:00
}
}
2014-11-25 16:00:58 -05:00
lldb : : ExpressionResults
2013-08-23 13:46:38 -04:00
ClangUserExpression : : Evaluate ( ExecutionContext & exe_ctx ,
2013-11-06 11:48:53 -05:00
const EvaluateExpressionOptions & options ,
2013-08-23 13:46:38 -04:00
const char * expr_cstr ,
const char * expr_prefix ,
lldb : : ValueObjectSP & result_valobj_sp ,
2013-11-06 11:48:53 -05:00
Error & error )
2013-08-23 13:46:38 -04:00
{
Log * log ( lldb_private : : GetLogIfAnyCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP ) ) ;
2013-11-06 11:48:53 -05:00
lldb_private : : ExecutionPolicy execution_policy = options . GetExecutionPolicy ( ) ;
const lldb : : LanguageType language = options . GetLanguage ( ) ;
const ResultType desired_type = options . DoesCoerceToId ( ) ? ClangUserExpression : : eResultTypeId : ClangUserExpression : : eResultTypeAny ;
2014-11-25 16:00:58 -05:00
lldb : : ExpressionResults execution_results = lldb : : eExpressionSetupError ;
2013-08-23 13:46:38 -04:00
Process * process = exe_ctx . GetProcessPtr ( ) ;
if ( process = = NULL | | process - > GetState ( ) ! = lldb : : eStateStopped )
{
if ( execution_policy = = eExecutionPolicyAlways )
{
if ( log )
log - > Printf ( " == [ClangUserExpression::Evaluate] Expression may not run, but is not constant == " ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
error . SetErrorString ( " expression needed to run but couldn't " ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
return execution_results ;
}
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( process = = NULL | | ! process - > CanJIT ( ) )
execution_policy = eExecutionPolicyNever ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
ClangUserExpressionSP user_expression_sp ( new ClangUserExpression ( expr_cstr , expr_prefix , language , desired_type ) ) ;
StreamString error_stream ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( log )
log - > Printf ( " == [ClangUserExpression::Evaluate] Parsing expression %s == " , expr_cstr ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
const bool keep_expression_in_memory = true ;
2014-11-25 16:00:58 -05:00
const bool generate_debug_info = options . GetGenerateDebugInfo ( ) ;
if ( options . InvokeCancelCallback ( lldb : : eExpressionEvaluationParse ) )
{
error . SetErrorString ( " expression interrupted by callback before parse " ) ;
result_valobj_sp = ValueObjectConstResult : : Create ( exe_ctx . GetBestExecutionContextScope ( ) , error ) ;
return lldb : : eExpressionInterrupted ;
}
if ( ! user_expression_sp - > Parse ( error_stream ,
exe_ctx ,
execution_policy ,
keep_expression_in_memory ,
generate_debug_info ) )
2013-08-23 13:46:38 -04:00
{
if ( error_stream . GetString ( ) . empty ( ) )
2014-11-25 16:00:58 -05:00
error . SetExpressionError ( lldb : : eExpressionParseError , " expression failed to parse, unknown error " ) ;
2013-08-23 13:46:38 -04:00
else
2014-11-25 16:00:58 -05:00
error . SetExpressionError ( lldb : : eExpressionParseError , error_stream . GetString ( ) . c_str ( ) ) ;
2013-08-23 13:46:38 -04:00
}
else
{
lldb : : ClangExpressionVariableSP expr_result ;
if ( execution_policy = = eExecutionPolicyNever & &
! user_expression_sp - > CanInterpret ( ) )
{
if ( log )
log - > Printf ( " == [ClangUserExpression::Evaluate] Expression may not run, but is not constant == " ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( error_stream . GetString ( ) . empty ( ) )
2014-11-25 16:00:58 -05:00
error . SetExpressionError ( lldb : : eExpressionSetupError , " expression needed to run but couldn't " ) ;
2013-08-23 13:46:38 -04:00
}
else
2014-11-25 16:00:58 -05:00
{
if ( options . InvokeCancelCallback ( lldb : : eExpressionEvaluationExecution ) )
{
error . SetExpressionError ( lldb : : eExpressionInterrupted , " expression interrupted by callback before execution " ) ;
result_valobj_sp = ValueObjectConstResult : : Create ( exe_ctx . GetBestExecutionContextScope ( ) , error ) ;
return lldb : : eExpressionInterrupted ;
}
2013-08-23 13:46:38 -04:00
error_stream . GetString ( ) . clear ( ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( log )
log - > Printf ( " == [ClangUserExpression::Evaluate] Executing expression == " ) ;
2014-11-25 16:00:58 -05:00
execution_results = user_expression_sp - > Execute ( error_stream ,
2013-11-06 11:48:53 -05:00
exe_ctx ,
options ,
user_expression_sp ,
expr_result ) ;
2014-11-25 16:00:58 -05:00
2015-02-06 16:38:51 -05:00
if ( options . GetResultIsInternal ( ) & & expr_result & & process )
2014-11-25 16:00:58 -05:00
{
process - > GetTarget ( ) . GetPersistentVariables ( ) . RemovePersistentVariable ( expr_result ) ;
}
if ( execution_results ! = lldb : : eExpressionCompleted )
2013-08-23 13:46:38 -04:00
{
if ( log )
log - > Printf ( " == [ClangUserExpression::Evaluate] Execution completed abnormally == " ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( error_stream . GetString ( ) . empty ( ) )
2014-11-25 16:00:58 -05:00
error . SetExpressionError ( execution_results , " expression failed to execute, unknown error " ) ;
2013-08-23 13:46:38 -04:00
else
2014-11-25 16:00:58 -05:00
error . SetExpressionError ( execution_results , error_stream . GetString ( ) . c_str ( ) ) ;
2013-08-23 13:46:38 -04:00
}
2014-11-25 16:00:58 -05:00
else
2013-08-23 13:46:38 -04:00
{
if ( expr_result )
{
result_valobj_sp = expr_result - > GetValueObject ( ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( log )
2014-11-25 16:00:58 -05:00
log - > Printf ( " == [ClangUserExpression::Evaluate] Execution completed normally with result %s == " ,
result_valobj_sp - > GetValueAsCString ( ) ) ;
2013-08-23 13:46:38 -04:00
}
else
{
if ( log )
log - > Printf ( " == [ClangUserExpression::Evaluate] Execution completed normally with no result == " ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
error . SetError ( ClangUserExpression : : kNoResult , lldb : : eErrorTypeGeneric ) ;
}
}
}
}
2014-11-25 16:00:58 -05:00
if ( options . InvokeCancelCallback ( lldb : : eExpressionEvaluationComplete ) )
{
error . SetExpressionError ( lldb : : eExpressionInterrupted , " expression interrupted by callback after complete " ) ;
return lldb : : eExpressionInterrupted ;
}
2013-08-23 13:46:38 -04:00
if ( result_valobj_sp . get ( ) = = NULL )
2014-02-18 11:23:10 -05:00
{
result_valobj_sp = ValueObjectConstResult : : Create ( exe_ctx . GetBestExecutionContextScope ( ) , error ) ;
}
2013-08-23 13:46:38 -04:00
return execution_results ;
}