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; 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) { diagnostic_manager.Printf(eDiagnosticSeverityError, "Couldn't execute function; result was %s", Process::ExecutionResultAsCString(execution_result)); return execution_result; } } 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; } }
unsigned ClangExpressionParser::ParseInternal(DiagnosticManager &diagnostic_manager, CodeCompleteConsumer *completion_consumer, unsigned completion_line, unsigned completion_column) { ClangDiagnosticManagerAdapter *adapter = static_cast<ClangDiagnosticManagerAdapter *>( m_compiler->getDiagnostics().getClient()); clang::TextDiagnosticBuffer *diag_buf = adapter->GetPassthrough(); diag_buf->FlushDiagnostics(m_compiler->getDiagnostics()); adapter->ResetManager(&diagnostic_manager); const char *expr_text = m_expr.Text(); clang::SourceManager &source_mgr = m_compiler->getSourceManager(); bool created_main_file = false; // Clang wants to do completion on a real file known by Clang's file manager, // so we have to create one to make this work. // TODO: We probably could also simulate to Clang's file manager that there // is a real file that contains our code. bool should_create_file = completion_consumer != nullptr; // We also want a real file on disk if we generate full debug info. should_create_file |= m_compiler->getCodeGenOpts().getDebugInfo() == codegenoptions::FullDebugInfo; if (should_create_file) { int temp_fd = -1; llvm::SmallString<128> result_path; if (FileSpec tmpdir_file_spec = HostInfo::GetProcessTempDir()) { tmpdir_file_spec.AppendPathComponent("lldb-%%%%%%.expr"); std::string temp_source_path = tmpdir_file_spec.GetPath(); llvm::sys::fs::createUniqueFile(temp_source_path, temp_fd, result_path); } else { llvm::sys::fs::createTemporaryFile("lldb", "expr", temp_fd, result_path); } if (temp_fd != -1) { lldb_private::File file(temp_fd, true); const size_t expr_text_len = strlen(expr_text); size_t bytes_written = expr_text_len; if (file.Write(expr_text, bytes_written).Success()) { if (bytes_written == expr_text_len) { file.Close(); source_mgr.setMainFileID( source_mgr.createFileID(m_file_manager->getFile(result_path), SourceLocation(), SrcMgr::C_User)); created_main_file = true; } } } } if (!created_main_file) { std::unique_ptr<MemoryBuffer> memory_buffer = MemoryBuffer::getMemBufferCopy(expr_text, __FUNCTION__); source_mgr.setMainFileID(source_mgr.createFileID(std::move(memory_buffer))); } diag_buf->BeginSourceFile(m_compiler->getLangOpts(), &m_compiler->getPreprocessor()); ClangExpressionHelper *type_system_helper = dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper()); ASTConsumer *ast_transformer = type_system_helper->ASTTransformer(m_code_generator.get()); if (ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap()) decl_map->InstallCodeGenerator(m_code_generator.get()); // If we want to parse for code completion, we need to attach our code // completion consumer to the Sema and specify a completion position. // While parsing the Sema will call this consumer with the provided // completion suggestions. if (completion_consumer) { auto main_file = source_mgr.getFileEntryForID(source_mgr.getMainFileID()); auto &PP = m_compiler->getPreprocessor(); // Lines and columns start at 1 in Clang, but code completion positions are // indexed from 0, so we need to add 1 to the line and column here. ++completion_line; ++completion_column; PP.SetCodeCompletionPoint(main_file, completion_line, completion_column); } if (ast_transformer) { ast_transformer->Initialize(m_compiler->getASTContext()); ParseAST(m_compiler->getPreprocessor(), ast_transformer, m_compiler->getASTContext(), false, TU_Complete, completion_consumer); } else { m_code_generator->Initialize(m_compiler->getASTContext()); ParseAST(m_compiler->getPreprocessor(), m_code_generator.get(), m_compiler->getASTContext(), false, TU_Complete, completion_consumer); } diag_buf->EndSourceFile(); unsigned num_errors = diag_buf->getNumErrors(); if (m_pp_callbacks && m_pp_callbacks->hasErrors()) { num_errors++; diagnostic_manager.PutString(eDiagnosticSeverityError, "while importing modules:"); diagnostic_manager.AppendMessageToDiagnostic( m_pp_callbacks->getErrorString()); } if (!num_errors) { if (type_system_helper->DeclMap() && !type_system_helper->DeclMap()->ResolveUnknownTypes()) { diagnostic_manager.Printf(eDiagnosticSeverityError, "Couldn't infer the type of a variable"); num_errors++; } } if (!num_errors) { type_system_helper->CommitPersistentDecls(); } adapter->ResetManager(); return num_errors; }
unsigned ClangExpressionParser::Parse(DiagnosticManager &diagnostic_manager) { ClangDiagnosticManagerAdapter *adapter = static_cast<ClangDiagnosticManagerAdapter *>(m_compiler->getDiagnostics().getClient()); clang::TextDiagnosticBuffer *diag_buf = adapter->GetPassthrough(); diag_buf->FlushDiagnostics(m_compiler->getDiagnostics()); adapter->ResetManager(&diagnostic_manager); const char *expr_text = m_expr.Text(); clang::SourceManager &source_mgr = m_compiler->getSourceManager(); bool created_main_file = false; if (m_compiler->getCodeGenOpts().getDebugInfo() == codegenoptions::FullDebugInfo) { int temp_fd = -1; llvm::SmallString<PATH_MAX> result_path; FileSpec tmpdir_file_spec; if (HostInfo::GetLLDBPath(lldb::ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) { tmpdir_file_spec.AppendPathComponent("lldb-%%%%%%.expr"); std::string temp_source_path = tmpdir_file_spec.GetPath(); llvm::sys::fs::createUniqueFile(temp_source_path, temp_fd, result_path); } else { llvm::sys::fs::createTemporaryFile("lldb", "expr", temp_fd, result_path); } if (temp_fd != -1) { lldb_private::File file(temp_fd, true); const size_t expr_text_len = strlen(expr_text); size_t bytes_written = expr_text_len; if (file.Write(expr_text, bytes_written).Success()) { if (bytes_written == expr_text_len) { file.Close(); source_mgr.setMainFileID(source_mgr.createFileID(m_file_manager->getFile(result_path), SourceLocation(), SrcMgr::C_User)); created_main_file = true; } } } } if (!created_main_file) { std::unique_ptr<MemoryBuffer> memory_buffer = MemoryBuffer::getMemBufferCopy(expr_text, __FUNCTION__); source_mgr.setMainFileID(source_mgr.createFileID(std::move(memory_buffer))); } diag_buf->BeginSourceFile(m_compiler->getLangOpts(), &m_compiler->getPreprocessor()); ClangExpressionHelper *type_system_helper = dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper()); ASTConsumer *ast_transformer = type_system_helper->ASTTransformer(m_code_generator.get()); if (ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap()) decl_map->InstallCodeGenerator(m_code_generator.get()); if (ast_transformer) { ast_transformer->Initialize(m_compiler->getASTContext()); ParseAST(m_compiler->getPreprocessor(), ast_transformer, m_compiler->getASTContext()); } else { m_code_generator->Initialize(m_compiler->getASTContext()); ParseAST(m_compiler->getPreprocessor(), m_code_generator.get(), m_compiler->getASTContext()); } diag_buf->EndSourceFile(); unsigned num_errors = diag_buf->getNumErrors(); if (m_pp_callbacks && m_pp_callbacks->hasErrors()) { num_errors++; diagnostic_manager.PutCString(eDiagnosticSeverityError, "while importing modules:"); diagnostic_manager.AppendMessageToDiagnostic(m_pp_callbacks->getErrorString().c_str()); } if (!num_errors) { if (type_system_helper->DeclMap() && !type_system_helper->DeclMap()->ResolveUnknownTypes()) { diagnostic_manager.Printf(eDiagnosticSeverityError, "Couldn't infer the type of a variable"); num_errors++; } } if (!num_errors) { type_system_helper->CommitPersistentDecls(); } adapter->ResetManager(); return num_errors; }
unsigned ClangExpressionParser::Parse (DiagnosticManager &diagnostic_manager, uint32_t first_line, uint32_t last_line, uint32_t line_offset) { ClangDiagnosticManagerAdapter *adapter = static_cast<ClangDiagnosticManagerAdapter *>(m_compiler->getDiagnostics().getClient()); clang::TextDiagnosticBuffer *diag_buf = adapter->GetPassthrough(); diag_buf->FlushDiagnostics(m_compiler->getDiagnostics()); adapter->ResetManager(&diagnostic_manager); const char *expr_text = m_expr.Text(); clang::SourceManager &SourceMgr = m_compiler->getSourceManager(); bool created_main_file = false; if (m_expr.GetOptions() && m_expr.GetOptions()->GetPoundLineFilePath() == NULL && m_compiler->getCodeGenOpts().getDebugInfo() == CodeGenOptions::FullDebugInfo) { std::string temp_source_path; if (ExpressionSourceCode::SaveExpressionTextToTempFile(expr_text, *m_expr.GetOptions(), temp_source_path)) { auto file = m_file_manager->getFile(temp_source_path); if (file) { SourceMgr.setMainFileID(SourceMgr.createFileID (file, SourceLocation(), SrcMgr::C_User)); created_main_file = true; } } } if (!created_main_file) { std::unique_ptr<MemoryBuffer> memory_buffer = MemoryBuffer::getMemBufferCopy(expr_text, __FUNCTION__); SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(memory_buffer))); } diag_buf->BeginSourceFile(m_compiler->getLangOpts(), &m_compiler->getPreprocessor()); ClangExpressionHelper *type_system_helper = dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper()); ASTConsumer *ast_transformer = type_system_helper->ASTTransformer(m_code_generator.get()); if (ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap()) decl_map->InstallCodeGenerator(m_code_generator.get()); if (ast_transformer) { ast_transformer->Initialize(m_compiler->getASTContext()); ParseAST(m_compiler->getPreprocessor(), ast_transformer, m_compiler->getASTContext()); } else { m_code_generator->Initialize(m_compiler->getASTContext()); ParseAST(m_compiler->getPreprocessor(), m_code_generator.get(), m_compiler->getASTContext()); } diag_buf->EndSourceFile(); unsigned num_errors = diag_buf->getNumErrors(); if (m_pp_callbacks && m_pp_callbacks->hasErrors()) { num_errors++; diagnostic_manager.PutCString(eDiagnosticSeverityError, "while importing modules:"); diagnostic_manager.AppendMessageToDiagnostic(m_pp_callbacks->getErrorString().c_str()); } if (!num_errors) { if (type_system_helper->DeclMap() && !type_system_helper->DeclMap()->ResolveUnknownTypes()) { diagnostic_manager.Printf(eDiagnosticSeverityError, "Couldn't infer the type of a variable"); num_errors++; } } if (!num_errors) { type_system_helper->CommitPersistentDecls(); } adapter->ResetManager(); return num_errors; }