lldb_private::Error ClangExpressionParser::RunStaticInitializers (lldb::IRExecutionUnitSP &execution_unit_sp, ExecutionContext &exe_ctx) { lldb_private::Error err; lldbassert(execution_unit_sp.get()); lldbassert(exe_ctx.HasThreadScope()); if (!execution_unit_sp.get()) { err.SetErrorString ("can't run static initializers for a NULL execution unit"); return err; } if (!exe_ctx.HasThreadScope()) { err.SetErrorString ("can't run static initializers without a thread"); return err; } std::vector<lldb::addr_t> static_initializers; execution_unit_sp->GetStaticInitializers(static_initializers); for (lldb::addr_t static_initializer : static_initializers) { EvaluateExpressionOptions options; lldb::ThreadPlanSP call_static_initializer(new ThreadPlanCallFunction(exe_ctx.GetThreadRef(), Address(static_initializer), CompilerType(), llvm::ArrayRef<lldb::addr_t>(), options)); DiagnosticManager execution_errors; lldb::ExpressionResults results = exe_ctx.GetThreadRef().GetProcess()->RunThreadPlan(exe_ctx, call_static_initializer, options, execution_errors); if (results != lldb::eExpressionCompleted) { err.SetErrorStringWithFormat ("couldn't run static initializer: %s", execution_errors.GetString().c_str()); return err; } } return err; }
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 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; } }