// This is the static function ExecutionResults ClangFunction::ExecuteFunction ( ExecutionContext &exe_ctx, lldb::addr_t function_address, lldb::addr_t &void_arg, bool stop_others, bool try_all_threads, bool discard_on_error, uint32_t single_thread_timeout_usec, Stream &errors, lldb::addr_t *this_arg) { lldb::ThreadPlanSP call_plan_sp (ClangFunction::GetThreadPlanToCallFunction (exe_ctx, function_address, void_arg, errors, stop_others, discard_on_error, this_arg)); if (call_plan_sp == NULL) return eExecutionSetupError; call_plan_sp->SetPrivate(true); return exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx, call_plan_sp, stop_others, try_all_threads, discard_on_error, single_thread_timeout_usec, errors); }
void ClangFunction::DeallocateFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t args_addr) { std::list<lldb::addr_t>::iterator pos; pos = std::find(m_wrapper_args_addrs.begin(), m_wrapper_args_addrs.end(), args_addr); if (pos != m_wrapper_args_addrs.end()) m_wrapper_args_addrs.erase(pos); exe_ctx.GetProcessRef().DeallocateMemory(args_addr); }
lldb::ExpressionResults ClangUserExpression::Execute (Stream &error_stream, ExecutionContext &exe_ctx, const EvaluateExpressionOptions& options, ClangUserExpression::ClangUserExpressionSP &shared_ptr_to_me, lldb::ClangExpressionVariableSP &result) { // 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; 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 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_sp->GetModule(); llvm::Function *function = m_execution_unit_sp->GetFunction(); if (!module || !function) { error_stream.Printf("Supposed to interpret, but nothing is there"); 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_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 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); 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 lldb::eExpressionSetupError; 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); 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 == 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(); 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 error_stream.PutCString ("Execution was interrupted."); 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 { 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 == lldb::eExpressionStoppedForDebug) { 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 != 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 lldb::eExpressionCompleted; } else { return lldb::eExpressionResultUnavailable; } } else { error_stream.Printf("Expression can't be run, because there is no JIT compiled function"); return lldb::eExpressionSetupError; } }
ExecutionResults ClangUserExpression::Execute (Stream &error_stream, ExecutionContext &exe_ctx, bool unwind_on_error, bool ignore_breakpoints, ClangUserExpression::ClangUserExpressionSP &shared_ptr_to_me, lldb::ClangExpressionVariableSP &result, bool run_others, uint32_t timeout_usec) { // 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; 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; } 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(); if (!module || !function) { error_stream.Printf("Supposed to interpret, but nothing is there"); return eExecutionSetupError; } 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(), 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; } } else { const bool stop_others = true; const bool try_all_threads = run_others; Address wrapper_address (m_jit_start_addr); lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression (exe_ctx.GetThreadRef(), wrapper_address, struct_address, stop_others, unwind_on_error, ignore_breakpoints, (m_needs_object_ptr ? &object_ptr : NULL), ((m_needs_object_ptr && m_objectivec) ? &cmd_ptr : NULL), shared_ptr_to_me)); 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(); function_stack_bottom = function_stack_pointer - Host::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, call_plan_sp, stop_others, try_all_threads, unwind_on_error, ignore_breakpoints, timeout_usec, 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) { const char *error_desc = NULL; 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 error_stream.Printf ("Execution was interrupted."); if ((execution_result == eExecutionInterrupted && unwind_on_error) || (execution_result == eExecutionHitBreakpoint && ignore_breakpoints)) error_stream.Printf ("\nThe process has been returned to the state before expression evaluation."); else error_stream.Printf ("\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 != eExecutionCompleted) { 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; } else { return eExecutionSetupError; } } else { error_stream.Printf("Expression can't be run, because there is no JIT compiled function"); return eExecutionSetupError; } }
lldb::ExpressionResults ClangFunction::ExecuteFunction( ExecutionContext &exe_ctx, lldb::addr_t *args_addr_ptr, const EvaluateExpressionOptions &options, Stream &errors, Value &results) { using namespace clang; lldb::ExpressionResults return_value = lldb::eExpressionSetupError; // ClangFunction::ExecuteFunction execution is always just to get the result. Do make sure we ignore // breakpoints, unwind on error, and don't try to debug it. EvaluateExpressionOptions real_options = options; real_options.SetDebug(false); real_options.SetUnwindOnError(true); real_options.SetIgnoreBreakpoints(true); lldb::addr_t args_addr; if (args_addr_ptr != NULL) args_addr = *args_addr_ptr; else args_addr = LLDB_INVALID_ADDRESS; if (CompileFunction(errors) != 0) return lldb::eExpressionSetupError; if (args_addr == LLDB_INVALID_ADDRESS) { if (!InsertFunction(exe_ctx, args_addr, errors)) return lldb::eExpressionSetupError; } Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); if (log) log->Printf("== [ClangFunction::ExecuteFunction] Executing function \"%s\" ==", m_name.c_str()); lldb::ThreadPlanSP call_plan_sp = GetThreadPlanToCallFunction (exe_ctx, args_addr, real_options, errors); if (!call_plan_sp) return lldb::eExpressionSetupError; // We need to make sure we record the fact that we are running an expression here // otherwise this fact will fail to be recorded when fetching an Objective-C object description if (exe_ctx.GetProcessPtr()) exe_ctx.GetProcessPtr()->SetRunningUserExpression(true); return_value = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx, call_plan_sp, real_options, errors); if (log) { if (return_value != lldb::eExpressionCompleted) { log->Printf("== [ClangFunction::ExecuteFunction] Execution of \"%s\" completed abnormally ==", m_name.c_str()); } else { log->Printf("== [ClangFunction::ExecuteFunction] Execution of \"%s\" completed normally ==", m_name.c_str()); } } if (exe_ctx.GetProcessPtr()) exe_ctx.GetProcessPtr()->SetRunningUserExpression(false); if (args_addr_ptr != NULL) *args_addr_ptr = args_addr; if (return_value != lldb::eExpressionCompleted) return return_value; FetchFunctionResults(exe_ctx, args_addr, results); if (args_addr_ptr == NULL) DeallocateFunctionResults(exe_ctx, args_addr); return lldb::eExpressionCompleted; }
lldb::ExpressionResults LLVMUserExpression::DoExecute(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options, lldb::UserExpressionSP &shared_ptr_to_me, lldb::ExpressionVariableSP &result) { // 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; if (!PrepareToExecuteJITExpression(diagnostic_manager, exe_ctx, struct_address)) { diagnostic_manager.Printf( eDiagnosticSeverityError, "errored out in %s, couldn't PrepareToExecuteJITExpression", __FUNCTION__); return lldb::eExpressionSetupError; } lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS; lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS; lldb::ValueObjectSP error_backstop_result_sp; if (m_can_interpret) { llvm::Module *module = m_execution_unit_sp->GetModule(); llvm::Function *function = m_execution_unit_sp->GetFunction(); if (!module || !function) { diagnostic_manager.PutCString( eDiagnosticSeverityError, "supposed to interpret, but nothing is there"); return lldb::eExpressionSetupError; } Error interpreter_error; std::vector<lldb::addr_t> args; if (!AddArguments(exe_ctx, args, struct_address, diagnostic_manager)) { diagnostic_manager.Printf(eDiagnosticSeverityError, "errored out in %s, couldn't AddArguments", __FUNCTION__); return lldb::eExpressionSetupError; } function_stack_bottom = m_stack_frame_bottom; function_stack_top = m_stack_frame_top; IRInterpreter::Interpret(*module, *function, args, *m_execution_unit_sp.get(), interpreter_error, function_stack_bottom, function_stack_top, exe_ctx); if (!interpreter_error.Success()) { diagnostic_manager.Printf(eDiagnosticSeverityError, "supposed to interpret, but failed: %s", interpreter_error.AsCString()); return lldb::eExpressionDiscarded; } } else { if (!exe_ctx.HasThreadScope()) { diagnostic_manager.Printf(eDiagnosticSeverityError, "%s called with no thread selected", __FUNCTION__); return lldb::eExpressionSetupError; } Address wrapper_address(m_jit_start_addr); std::vector<lldb::addr_t> args; if (!AddArguments(exe_ctx, args, struct_address, diagnostic_manager)) { diagnostic_manager.Printf(eDiagnosticSeverityError, "errored out in %s, couldn't AddArguments", __FUNCTION__); return lldb::eExpressionSetupError; } lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression( exe_ctx.GetThreadRef(), wrapper_address, args, options, shared_ptr_to_me)); StreamString ss; if (!call_plan_sp || !call_plan_sp->ValidatePlan(&ss)) { diagnostic_manager.PutCString(eDiagnosticSeverityError, ss.GetData()); return lldb::eExpressionSetupError; } ThreadPlanCallUserExpression *user_expression_plan = static_cast<ThreadPlanCallUserExpression *>(call_plan_sp.get()); 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( "-- [UserExpression::Execute] Execution of expression begins --"); if (exe_ctx.GetProcessPtr()) exe_ctx.GetProcessPtr()->SetRunningUserExpression(true); lldb::ExpressionResults execution_result = exe_ctx.GetProcessRef().RunThreadPlan(exe_ctx, call_plan_sp, options, diagnostic_manager); if (exe_ctx.GetProcessPtr()) exe_ctx.GetProcessPtr()->SetRunningUserExpression(false); if (log) log->Printf("-- [UserExpression::Execute] Execution of expression " "completed --"); 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(); if (real_stop_info_sp) error_desc = real_stop_info_sp->GetDescription(); } if (error_desc) diagnostic_manager.Printf(eDiagnosticSeverityError, "Execution was interrupted, reason: %s.", error_desc); else diagnostic_manager.PutCString(eDiagnosticSeverityError, "Execution was interrupted."); if ((execution_result == lldb::eExpressionInterrupted && options.DoesUnwindOnError()) || (execution_result == lldb::eExpressionHitBreakpoint && options.DoesIgnoreBreakpoints())) diagnostic_manager.AppendMessageToDiagnostic( "The process has been returned to the state before expression " "evaluation."); else { if (execution_result == lldb::eExpressionHitBreakpoint) user_expression_plan->TransferExpressionOwnership(); diagnostic_manager.AppendMessageToDiagnostic( "The 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 == lldb::eExpressionStoppedForDebug) { diagnostic_manager.PutCString( eDiagnosticSeverityRemark, "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 == lldb::eExpressionCompleted) { if (user_expression_plan->HitErrorBackstop()) { // This should only happen in Playground & REPL. The code threw an // uncaught error, so we already rolled up // the stack past our execution point. We're not going to be able to // get any or our expression variables // since they've already gone out of scope. But at least we can // gather the error result... if (user_expression_plan->GetReturnValueObject() && user_expression_plan->GetReturnValueObject() ->GetError() .Success()) { error_backstop_result_sp = user_expression_plan->GetReturnValueObject(); } } } else { diagnostic_manager.Printf( eDiagnosticSeverityError, "Couldn't execute function; result was %s", Process::ExecutionResultAsCString(execution_result)); return execution_result; } } if (error_backstop_result_sp) { // This should only happen in Playground & REPL. The code threw an // uncaught error, so we already rolled up // the stack past our execution point. We're not going to be able to get // any or our expression variables // since they've already gone out of scope. But at least we can gather // the error result... Target *target = exe_ctx.GetTargetPtr(); PersistentExpressionState *expression_state = target->GetPersistentExpressionStateForLanguage(Language()); if (expression_state) result = expression_state->CreatePersistentVariable( error_backstop_result_sp); return lldb::eExpressionCompleted; } else if (FinalizeJITExecution(diagnostic_manager, exe_ctx, result, function_stack_bottom, function_stack_top)) { return lldb::eExpressionCompleted; } else { return lldb::eExpressionResultUnavailable; } } else { diagnostic_manager.PutCString( eDiagnosticSeverityError, "Expression can't be run, because there is no JIT compiled function"); return lldb::eExpressionSetupError; } }