diff options
author | emaste <emaste@FreeBSD.org> | 2014-11-26 16:48:12 +0000 |
---|---|---|
committer | emaste <emaste@FreeBSD.org> | 2014-11-26 16:48:12 +0000 |
commit | 0147dda7de9580d13778ecb4c9e92b83b7a63911 (patch) | |
tree | b16dc95f693ed59342b6141cd3fd9f59a6cd7e7e /contrib/llvm/tools/lldb/source/Expression/ClangUserExpression.cpp | |
parent | bfd4c39c61ae9b29542625bb12b6f7f4b1f8c727 (diff) | |
parent | 01ee1789d6aa7294e5966a97f8d29387f6f81699 (diff) | |
download | FreeBSD-src-0147dda7de9580d13778ecb4c9e92b83b7a63911.zip FreeBSD-src-0147dda7de9580d13778ecb4c9e92b83b7a63911.tar.gz |
Update LLDB snapshot to upstream r216948 (git 50f7fe44)
This is approximately "LLDB 3.5" although with a little bit of skew,
and will go along with the Clang 3.5 import.
Sponsored by: DARPA, AFRL
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Expression/ClangUserExpression.cpp')
-rw-r--r-- | contrib/llvm/tools/lldb/source/Expression/ClangUserExpression.cpp | 541 |
1 files changed, 315 insertions, 226 deletions
diff --git a/contrib/llvm/tools/lldb/source/Expression/ClangUserExpression.cpp b/contrib/llvm/tools/lldb/source/Expression/ClangUserExpression.cpp index 6b0eee8..52ef4d3 100644 --- a/contrib/llvm/tools/lldb/source/Expression/ClangUserExpression.cpp +++ b/contrib/llvm/tools/lldb/source/Expression/ClangUserExpression.cpp @@ -7,19 +7,18 @@ // //===----------------------------------------------------------------------===// -// C Includes #include <stdio.h> #if HAVE_SYS_TYPES_H # include <sys/types.h> #endif -// C++ Includes #include <cstdlib> #include <string> #include <map> #include "lldb/Core/ConstString.h" #include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/ValueObjectConstResult.h" @@ -32,10 +31,12 @@ #include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Expression/IRInterpreter.h" #include "lldb/Expression/Materializer.h" -#include "lldb/Host/Host.h" +#include "lldb/Host/HostInfo.h" #include "lldb/Symbol/Block.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/Function.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/Type.h" #include "lldb/Symbol/ClangExternalASTSourceCommon.h" #include "lldb/Symbol/VariableList.h" @@ -63,6 +64,11 @@ ClangUserExpression::ClangUserExpression (const char *expr, m_language (language), m_transformed_text (), m_desired_type (desired_type), + m_expr_decl_map(), + m_execution_unit_sp(), + m_materializer_ap(), + m_result_synthesizer(), + m_jit_module_wp(), m_enforce_valid_object (true), m_cplusplus (false), m_objectivec (false), @@ -91,6 +97,12 @@ ClangUserExpression::ClangUserExpression (const char *expr, ClangUserExpression::~ClangUserExpression () { + if (m_target) + { + lldb::ModuleSP jit_module_sp (m_jit_module_wp.lock()); + if (jit_module_sp) + m_target->GetImages().Remove(jit_module_sp); + } } clang::ASTConsumer * @@ -98,7 +110,7 @@ ClangUserExpression::ASTTransformer (clang::ASTConsumer *passthrough) { m_result_synthesizer.reset(new ASTResultSynthesizer(passthrough, *m_target)); - + return m_result_synthesizer.get(); } @@ -109,16 +121,16 @@ ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err) if (log) log->Printf("ClangUserExpression::ScanContext()"); - + m_target = exe_ctx.GetTargetPtr(); - + if (!(m_allow_cxx || m_allow_objc)) { if (log) log->Printf(" [CUE::SC] Settings inhibit C++ and Objective-C"); return; } - + StackFrame *frame = exe_ctx.GetFramePtr(); if (frame == NULL) { @@ -126,19 +138,19 @@ ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err) log->Printf(" [CUE::SC] Null stack frame"); return; } - + SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction | lldb::eSymbolContextBlock); - + if (!sym_ctx.function) { if (log) log->Printf(" [CUE::SC] Null function"); return; } - + // Find the block that defines the function represented by "sym_ctx" Block *function_block = sym_ctx.GetFunctionBlock(); - + if (!function_block) { if (log) @@ -154,7 +166,7 @@ ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err) log->Printf(" [CUE::SC] Null decl context"); return; } - + if (clang::CXXMethodDecl *method_decl = llvm::dyn_cast<clang::CXXMethodDecl>(decl_context)) { if (m_allow_cxx && method_decl->isInstance()) @@ -162,60 +174,60 @@ ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err) if (m_enforce_valid_object) { lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true)); - + const char *thisErrorString = "Stopped in a C++ method, but 'this' isn't available; pretending we are in a generic context"; - + if (!variable_list_sp) { err.SetErrorString(thisErrorString); return; } - + lldb::VariableSP this_var_sp (variable_list_sp->FindVariable(ConstString("this"))); - + if (!this_var_sp || - !this_var_sp->IsInScope(frame) || + !this_var_sp->IsInScope(frame) || !this_var_sp->LocationIsValidForFrame (frame)) { err.SetErrorString(thisErrorString); return; } } - + m_cplusplus = true; m_needs_object_ptr = true; } } else if (clang::ObjCMethodDecl *method_decl = llvm::dyn_cast<clang::ObjCMethodDecl>(decl_context)) - { + { if (m_allow_objc) { if (m_enforce_valid_object) { lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true)); - + const char *selfErrorString = "Stopped in an Objective-C method, but 'self' isn't available; pretending we are in a generic context"; - + if (!variable_list_sp) { err.SetErrorString(selfErrorString); return; } - + lldb::VariableSP self_variable_sp = variable_list_sp->FindVariable(ConstString("self")); - - if (!self_variable_sp || - !self_variable_sp->IsInScope(frame) || + + if (!self_variable_sp || + !self_variable_sp->IsInScope(frame) || !self_variable_sp->LocationIsValidForFrame (frame)) { err.SetErrorString(selfErrorString); return; } } - + m_objectivec = true; m_needs_object_ptr = true; - + if (!method_decl->isInstanceMethod()) m_static_method = true; } @@ -226,7 +238,7 @@ ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err) // 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. - + ClangASTMetadata *metadata = ClangASTContext::GetMetadata (&decl_context->getParentASTContext(), function_decl); if (metadata && metadata->HasObjectPtr()) { @@ -236,17 +248,17 @@ ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err) if (m_enforce_valid_object) { lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true)); - + 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"; - + if (!variable_list_sp) { err.SetErrorString(thisErrorString); return; } - + lldb::VariableSP this_var_sp (variable_list_sp->FindVariable(ConstString("this"))); - + if (!this_var_sp || !this_var_sp->IsInScope(frame) || !this_var_sp->LocationIsValidForFrame (frame)) @@ -255,7 +267,7 @@ ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err) return; } } - + m_cplusplus = true; m_needs_object_ptr = true; } @@ -264,17 +276,17 @@ ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err) if (m_enforce_valid_object) { lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true)); - + 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"; - + if (!variable_list_sp) { err.SetErrorString(selfErrorString); return; } - + lldb::VariableSP self_variable_sp = variable_list_sp->FindVariable(ConstString("self")); - + if (!self_variable_sp || !self_variable_sp->IsInScope(frame) || !self_variable_sp->LocationIsValidForFrame (frame)) @@ -282,23 +294,23 @@ ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err) err.SetErrorString(selfErrorString); return; } - + Type *self_type = self_variable_sp->GetType(); - + if (!self_type) { err.SetErrorString(selfErrorString); return; } - + ClangASTType self_clang_type = self_type->GetClangForwardType(); - + if (!self_clang_type) { err.SetErrorString(selfErrorString); return; } - + if (self_clang_type.IsObjCClassType()) { return; @@ -328,9 +340,9 @@ void ClangUserExpression::InstallContext (ExecutionContext &exe_ctx) { m_process_wp = exe_ctx.GetProcessSP(); - + lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP(); - + if (frame_sp) m_address = frame_sp->GetFrameCodeAddress(); } @@ -346,11 +358,11 @@ ClangUserExpression::LockAndCheckContext (ExecutionContext &exe_ctx, if (process_sp != expected_process_sp) return false; - + process_sp = exe_ctx.GetProcessSP(); target_sp = exe_ctx.GetTargetSP(); frame_sp = exe_ctx.GetFrameSP(); - + if (m_address.IsValid()) { if (!frame_sp) @@ -358,7 +370,7 @@ ClangUserExpression::LockAndCheckContext (ExecutionContext &exe_ctx, else return (0 == Address::CompareLoadAddress(m_address, frame_sp->GetFrameCodeAddress(), target_sp.get())); } - + return true; } @@ -368,7 +380,7 @@ ClangUserExpression::MatchesContext (ExecutionContext &exe_ctx) lldb::TargetSP target_sp; lldb::ProcessSP process_sp; lldb::StackFrameSP frame_sp; - + return LockAndCheckContext(exe_ctx, target_sp, process_sp, frame_sp); } @@ -383,7 +395,7 @@ ApplyObjcCastHack(std::string &expr) #define OBJC_CAST_HACK_TO "(int)(long long)[" size_t from_offset; - + 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); @@ -396,99 +408,100 @@ ApplyObjcCastHack(std::string &expr) // 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. -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 -} +//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 +//} bool -ClangUserExpression::Parse (Stream &error_stream, +ClangUserExpression::Parse (Stream &error_stream, ExecutionContext &exe_ctx, lldb_private::ExecutionPolicy execution_policy, - bool keep_result_in_memory) + bool keep_result_in_memory, + bool generate_debug_info) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - + Error err; - + InstallContext(exe_ctx); - + ScanContext(exe_ctx, err); - + if (!err.Success()) { error_stream.Printf("warning: %s\n", err.AsCString()); } - + StreamString m_transformed_stream; - + //////////////////////////////////// // Generate the expression // - + 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())); - + lldb::LanguageType lang_type; - + if (m_cplusplus) lang_type = lldb::eLanguageTypeC_plus_plus; else if(m_objectivec) lang_type = lldb::eLanguageTypeObjC; else lang_type = lldb::eLanguageTypeC; - - if (!source_code->GetText(m_transformed_text, lang_type, m_const_object, m_static_method)) + + if (!source_code->GetText(m_transformed_text, lang_type, m_const_object, m_static_method, exe_ctx)) { error_stream.PutCString ("error: couldn't construct expression body"); return false; } - + if (log) log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str()); - + //////////////////////////////////// // Set up the target and compiler // - + Target *target = exe_ctx.GetTargetPtr(); - + if (!target) { error_stream.PutCString ("error: invalid target\n"); return false; } - + ////////////////////////// // Parse the expression // - + m_materializer_ap.reset(new Materializer()); - + m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx)); - + class OnExit { public: typedef std::function <void (void)> Callback; - + OnExit (Callback const &callback) : m_callback(callback) { } - + ~OnExit () { m_callback(); @@ -496,50 +509,81 @@ ClangUserExpression::Parse (Stream &error_stream, private: Callback m_callback; }; - + OnExit on_exit([this]() { m_expr_decl_map.reset(); }); - + 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"); - + m_expr_decl_map.reset(); // We are being careful here in the case of breakpoint conditions. - + return false; } - + Process *process = exe_ctx.GetProcessPtr(); ExecutionContextScope *exe_scope = process; - + if (!exe_scope) exe_scope = exe_ctx.GetTargetPtr(); - - ClangExpressionParser parser(exe_scope, *this); - + + ClangExpressionParser parser(exe_scope, *this, generate_debug_info); + unsigned num_errors = parser.Parse (error_stream); - + if (num_errors) { error_stream.Printf ("error: %d errors parsing expression\n", num_errors); - + m_expr_decl_map.reset(); // We are being careful here in the case of breakpoint conditions. - + return false; } - + ////////////////////////////////////////////////////////////////////////////////////////// // Prepare the output of the parser for execution, evaluating it statically if possible // - + Error jit_error = parser.PrepareForExecution (m_jit_start_addr, m_jit_end_addr, - m_execution_unit_ap, + m_execution_unit_sp, exe_ctx, m_can_interpret, execution_policy); - + + 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); +// } + } + 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. - + if (jit_error.Success()) { if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS) @@ -563,16 +607,16 @@ GetObjectPointer (lldb::StackFrameSP frame_sp, Error &err) { err.Clear(); - + if (!frame_sp) { err.SetErrorStringWithFormat("Couldn't load '%s' because the context is incomplete", object_name.AsCString()); return LLDB_INVALID_ADDRESS; } - + lldb::VariableSP var_sp; lldb::ValueObjectSP valobj_sp; - + valobj_sp = frame_sp->GetValueForVariableExpressionPath(object_name.AsCString(), lldb::eNoDynamicValues, StackFrame::eExpressionPathOptionCheckPtrVsMember || @@ -582,18 +626,18 @@ GetObjectPointer (lldb::StackFrameSP frame_sp, StackFrame::eExpressionPathOptionsNoSyntheticArrayRange, var_sp, err); - + if (!err.Success()) return LLDB_INVALID_ADDRESS; - + lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); - + 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; } - + return ret; } @@ -607,22 +651,22 @@ ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream, lldb::TargetSP target; lldb::ProcessSP process; lldb::StackFrameSP frame; - + if (!LockAndCheckContext(exe_ctx, target, - process, + process, frame)) { error_stream.Printf("The context has changed before we could JIT the expression!\n"); return false; } - + if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret) - { + { if (m_needs_object_ptr) { ConstString object_name; - + if (m_cplusplus) { object_name.SetCString("this"); @@ -636,23 +680,23 @@ ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream, error_stream.Printf("Need object pointer but don't know the language\n"); return false; } - + Error object_ptr_error; - + object_ptr = GetObjectPointer(frame, object_name, object_ptr_error); - + 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; } - + if (m_objectivec) { ConstString cmd_name("_cmd"); - + cmd_ptr = GetObjectPointer(frame, cmd_name, object_ptr_error); - + if (!object_ptr_error.Success()) { error_stream.Printf("warning: couldn't get cmd pointer (substituting NULL): %s\n", object_ptr_error.AsCString()); @@ -660,56 +704,56 @@ ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream, } } } - + if (m_materialized_address == LLDB_INVALID_ADDRESS) { Error alloc_error; - + IRMemoryMap::AllocationPolicy policy = m_can_interpret ? IRMemoryMap::eAllocationPolicyHostOnly : IRMemoryMap::eAllocationPolicyMirror; - - m_materialized_address = m_execution_unit_ap->Malloc(m_materializer_ap->GetStructByteSize(), + + m_materialized_address = m_execution_unit_sp->Malloc(m_materializer_ap->GetStructByteSize(), m_materializer_ap->GetStructAlignment(), lldb::ePermissionsReadable | lldb::ePermissionsWritable, policy, alloc_error); - + if (!alloc_error.Success()) { error_stream.Printf("Couldn't allocate space for materialized struct: %s\n", alloc_error.AsCString()); return false; } } - + struct_address = m_materialized_address; - + if (m_can_interpret && m_stack_frame_bottom == LLDB_INVALID_ADDRESS) { Error alloc_error; const size_t stack_frame_size = 512 * 1024; - - m_stack_frame_bottom = m_execution_unit_ap->Malloc(stack_frame_size, + + m_stack_frame_bottom = m_execution_unit_sp->Malloc(stack_frame_size, 8, lldb::ePermissionsReadable | lldb::ePermissionsWritable, IRMemoryMap::eAllocationPolicyHostOnly, alloc_error); - + m_stack_frame_top = m_stack_frame_bottom + stack_frame_size; - + if (!alloc_error.Success()) { error_stream.Printf("Couldn't allocate space for the stack frame: %s\n", alloc_error.AsCString()); return false; } } - + Error materialize_error; - - m_dematerializer_sp = m_materializer_ap->Materialize(frame, *m_execution_unit_ap, struct_address, materialize_error); - + + m_dematerializer_sp = m_materializer_ap->Materialize(frame, *m_execution_unit_sp, struct_address, materialize_error); + if (!materialize_error.Success()) { - error_stream.Printf("Couldn't materialize struct: %s\n", materialize_error.AsCString()); + error_stream.Printf("Couldn't materialize: %s\n", materialize_error.AsCString()); return false; } } @@ -724,18 +768,18 @@ ClangUserExpression::FinalizeJITExecution (Stream &error_stream, lldb::addr_t function_stack_top) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - + if (log) log->Printf("-- [ClangUserExpression::FinalizeJITExecution] Dematerializing after execution --"); - + if (!m_dematerializer_sp) { error_stream.Printf ("Couldn't apply expression side effects : no dematerializer is present"); return false; } - + Error dematerialize_error; - + m_dematerializer_sp->Dematerialize(dematerialize_error, result, function_stack_bottom, function_stack_top); if (!dematerialize_error.Success()) @@ -743,16 +787,16 @@ ClangUserExpression::FinalizeJITExecution (Stream &error_stream, error_stream.Printf ("Couldn't apply expression side effects : %s\n", dematerialize_error.AsCString("unknown error")); return false; } - + if (result) result->TransferAddress(); - + m_dematerializer_sp.reset(); - + return true; -} +} -ExecutionResults +lldb::ExpressionResults ClangUserExpression::Execute (Stream &error_stream, ExecutionContext &exe_ctx, const EvaluateExpressionOptions& options, @@ -766,110 +810,118 @@ ClangUserExpression::Execute (Stream &error_stream, if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret) { lldb::addr_t struct_address = LLDB_INVALID_ADDRESS; - + lldb::addr_t object_ptr = 0; lldb::addr_t cmd_ptr = 0; - + if (!PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr, cmd_ptr)) { error_stream.Printf("Errored out in %s, couldn't PrepareToExecuteJITExpression", __FUNCTION__); - return eExecutionSetupError; + return lldb::eExpressionSetupError; } - + lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS; lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS; - + if (m_can_interpret) - { - llvm::Module *module = m_execution_unit_ap->GetModule(); - llvm::Function *function = m_execution_unit_ap->GetFunction(); - + { + llvm::Module *module = m_execution_unit_sp->GetModule(); + llvm::Function *function = m_execution_unit_sp->GetFunction(); + if (!module || !function) { error_stream.Printf("Supposed to interpret, but nothing is there"); - return eExecutionSetupError; + return lldb::eExpressionSetupError; } Error interpreter_error; - + llvm::SmallVector <lldb::addr_t, 3> args; - + if (m_needs_object_ptr) { args.push_back(object_ptr); - + if (m_objectivec) args.push_back(cmd_ptr); } - + args.push_back(struct_address); - + function_stack_bottom = m_stack_frame_bottom; function_stack_top = m_stack_frame_top; - + IRInterpreter::Interpret (*module, *function, args, - *m_execution_unit_ap.get(), + *m_execution_unit_sp.get(), interpreter_error, function_stack_bottom, function_stack_top); - + if (!interpreter_error.Success()) { error_stream.Printf("Supposed to interpret, but failed: %s", interpreter_error.AsCString()); - return eExecutionDiscarded; + return lldb::eExpressionDiscarded; } } else { + if (!exe_ctx.HasThreadScope()) + { + error_stream.Printf("ClangUserExpression::Execute called with no thread selected."); + return lldb::eExpressionSetupError; + } + Address wrapper_address (m_jit_start_addr); - + llvm::SmallVector <lldb::addr_t, 3> args; - + if (m_needs_object_ptr) { args.push_back(object_ptr); if (m_objectivec) args.push_back(cmd_ptr); } - + args.push_back(struct_address); - - lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression (exe_ctx.GetThreadRef(), - wrapper_address, - args, - options, - shared_ptr_to_me)); - + + ThreadPlanCallUserExpression *user_expression_plan = + new ThreadPlanCallUserExpression (exe_ctx.GetThreadRef(), + wrapper_address, + args, + options, + shared_ptr_to_me); + lldb::ThreadPlanSP call_plan_sp(user_expression_plan); + if (!call_plan_sp || !call_plan_sp->ValidatePlan (&error_stream)) - return eExecutionSetupError; - - lldb::addr_t function_stack_pointer = static_cast<ThreadPlanCallFunction *>(call_plan_sp.get())->GetFunctionStackPointer(); + return lldb::eExpressionSetupError; - function_stack_bottom = function_stack_pointer - Host::GetPageSize(); + lldb::addr_t function_stack_pointer = user_expression_plan->GetFunctionStackPointer(); + + function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize(); function_stack_top = function_stack_pointer; - + if (log) log->Printf("-- [ClangUserExpression::Execute] Execution of expression begins --"); - + if (exe_ctx.GetProcessPtr()) exe_ctx.GetProcessPtr()->SetRunningUserExpression(true); - - ExecutionResults execution_result = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx, + + lldb::ExpressionResults execution_result = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx, call_plan_sp, options, error_stream); - + if (exe_ctx.GetProcessPtr()) exe_ctx.GetProcessPtr()->SetRunningUserExpression(false); - + if (log) log->Printf("-- [ClangUserExpression::Execute] Execution of expression completed --"); - if (execution_result == eExecutionInterrupted || execution_result == eExecutionHitBreakpoint) + if (execution_result == lldb::eExpressionInterrupted || execution_result == lldb::eExpressionHitBreakpoint) { const char *error_desc = NULL; - + if (call_plan_sp) { lldb::StopInfoSP real_stop_info_sp = call_plan_sp->GetRealStopInfo(); @@ -880,45 +932,51 @@ ClangUserExpression::Execute (Stream &error_stream, error_stream.Printf ("Execution was interrupted, reason: %s.", error_desc); else error_stream.PutCString ("Execution was interrupted."); - - if ((execution_result == eExecutionInterrupted && options.DoesUnwindOnError()) - || (execution_result == eExecutionHitBreakpoint && options.DoesIgnoreBreakpoints())) + + if ((execution_result == lldb::eExpressionInterrupted && options.DoesUnwindOnError()) + || (execution_result == lldb::eExpressionHitBreakpoint && options.DoesIgnoreBreakpoints())) error_stream.PutCString ("\nThe process has been returned to the state before expression evaluation."); else - error_stream.PutCString ("\nThe process has been left at the point where it was interrupted, use \"thread return -x\" to return to the state before expression evaluation."); + { + if (execution_result == lldb::eExpressionHitBreakpoint) + user_expression_plan->TransferExpressionOwnership(); + error_stream.PutCString ("\nThe process has been left at the point where it was interrupted, " + "use \"thread return -x\" to return to the state before expression evaluation."); + } return execution_result; } - else if (execution_result == eExecutionStoppedForDebug) + else if (execution_result == lldb::eExpressionStoppedForDebug) { - error_stream.PutCString ("Execution was halted at the first instruction of the expression function because \"debug\" was requested.\n" + error_stream.PutCString ("Execution was halted at the first instruction of the expression " + "function because \"debug\" was requested.\n" "Use \"thread return -x\" to return to the state before expression evaluation."); return execution_result; } - else if (execution_result != eExecutionCompleted) + else if (execution_result != lldb::eExpressionCompleted) { error_stream.Printf ("Couldn't execute function; result was %s\n", Process::ExecutionResultAsCString (execution_result)); return execution_result; } } - + if (FinalizeJITExecution (error_stream, exe_ctx, result, function_stack_bottom, function_stack_top)) { - return eExecutionCompleted; + return lldb::eExpressionCompleted; } else { - return eExecutionSetupError; + return lldb::eExpressionResultUnavailable; } } else { error_stream.Printf("Expression can't be run, because there is no JIT compiled function"); - return eExecutionSetupError; + return lldb::eExpressionSetupError; } } -ExecutionResults +lldb::ExpressionResults ClangUserExpression::Evaluate (ExecutionContext &exe_ctx, const EvaluateExpressionOptions& options, const char *expr_cstr, @@ -931,8 +989,8 @@ ClangUserExpression::Evaluate (ExecutionContext &exe_ctx, lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy(); const lldb::LanguageType language = options.GetLanguage(); const ResultType desired_type = options.DoesCoerceToId() ? ClangUserExpression::eResultTypeId : ClangUserExpression::eResultTypeAny; - ExecutionResults execution_results = eExecutionSetupError; - + lldb::ExpressionResults execution_results = lldb::eExpressionSetupError; + Process *process = exe_ctx.GetProcessPtr(); if (process == NULL || process->GetState() != lldb::eStateStopped) @@ -941,31 +999,43 @@ ClangUserExpression::Evaluate (ExecutionContext &exe_ctx, { if (log) log->Printf("== [ClangUserExpression::Evaluate] Expression may not run, but is not constant =="); - + error.SetErrorString ("expression needed to run but couldn't"); - + return execution_results; } } - + if (process == NULL || !process->CanJIT()) execution_policy = eExecutionPolicyNever; - + ClangUserExpressionSP user_expression_sp (new ClangUserExpression (expr_cstr, expr_prefix, language, desired_type)); StreamString error_stream; - + if (log) log->Printf("== [ClangUserExpression::Evaluate] Parsing expression %s ==", expr_cstr); - + const bool keep_expression_in_memory = true; - - if (!user_expression_sp->Parse (error_stream, exe_ctx, execution_policy, keep_expression_in_memory)) + 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)) { if (error_stream.GetString().empty()) - error.SetErrorString ("expression failed to parse, unknown error"); + error.SetExpressionError (lldb::eExpressionParseError, "expression failed to parse, unknown error"); else - error.SetErrorString (error_stream.GetString().c_str()); + error.SetExpressionError (lldb::eExpressionParseError, error_stream.GetString().c_str()); } else { @@ -976,53 +1046,72 @@ ClangUserExpression::Evaluate (ExecutionContext &exe_ctx, { if (log) log->Printf("== [ClangUserExpression::Evaluate] Expression may not run, but is not constant =="); - + if (error_stream.GetString().empty()) - error.SetErrorString ("expression needed to run but couldn't"); + error.SetExpressionError (lldb::eExpressionSetupError, "expression needed to run but couldn't"); } else - { + { + 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; + } + error_stream.GetString().clear(); - + if (log) log->Printf("== [ClangUserExpression::Evaluate] Executing expression =="); - execution_results = user_expression_sp->Execute (error_stream, + execution_results = user_expression_sp->Execute (error_stream, exe_ctx, options, user_expression_sp, expr_result); - - if (execution_results != eExecutionCompleted) + + if (options.GetResultIsInternal()) + { + process->GetTarget().GetPersistentVariables().RemovePersistentVariable (expr_result); + } + + if (execution_results != lldb::eExpressionCompleted) { if (log) log->Printf("== [ClangUserExpression::Evaluate] Execution completed abnormally =="); - + if (error_stream.GetString().empty()) - error.SetErrorString ("expression failed to execute, unknown error"); + error.SetExpressionError (execution_results, "expression failed to execute, unknown error"); else - error.SetErrorString (error_stream.GetString().c_str()); + error.SetExpressionError (execution_results, error_stream.GetString().c_str()); } - else + else { if (expr_result) { result_valobj_sp = expr_result->GetValueObject(); - + if (log) - log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with result %s ==", result_valobj_sp->GetValueAsCString()); + log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with result %s ==", + result_valobj_sp->GetValueAsCString()); } else { if (log) log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with no result =="); - + error.SetError(ClangUserExpression::kNoResult, lldb::eErrorTypeGeneric); } } } } - + + if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete)) + { + error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback after complete"); + return lldb::eExpressionInterrupted; + } + if (result_valobj_sp.get() == NULL) { result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error); |