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)); 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()) { 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; }
Error ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_allocation_addr, lldb::addr_t &func_addr, lldb::addr_t &func_end, ExecutionContext &exe_ctx, IRForTarget::StaticDataAllocator *data_allocator, bool &evaluated_statically, lldb::ClangExpressionVariableSP &const_result, ExecutionPolicy execution_policy) { func_allocation_addr = LLDB_INVALID_ADDRESS; func_addr = LLDB_INVALID_ADDRESS; func_end = LLDB_INVALID_ADDRESS; lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); std::auto_ptr<llvm::ExecutionEngine> execution_engine; Error err; llvm::Module *module = m_code_generator->ReleaseModule(); if (!module) { err.SetErrorToGenericError(); err.SetErrorString("IR doesn't contain a module"); return err; } // Find the actual name of the function (it's often mangled somehow) std::string function_name; if (!FindFunctionInModule(function_name, module, m_expr.FunctionName())) { err.SetErrorToGenericError(); err.SetErrorStringWithFormat("Couldn't find %s() in the module", m_expr.FunctionName()); return err; } else { if (log) log->Printf("Found function %s for %s", function_name.c_str(), m_expr.FunctionName()); } ClangExpressionDeclMap *decl_map = m_expr.DeclMap(); // result can be NULL if (decl_map) { Stream *error_stream = NULL; Target *target = exe_ctx.GetTargetPtr(); if (target) error_stream = &target->GetDebugger().GetErrorStream(); IRForTarget ir_for_target(decl_map, m_expr.NeedsVariableResolution(), execution_policy, const_result, data_allocator, error_stream, function_name.c_str()); ir_for_target.runOnModule(*module); Error &interpreter_error(ir_for_target.getInterpreterError()); if (execution_policy != eExecutionPolicyAlways && interpreter_error.Success()) { if (const_result) const_result->TransferAddress(); evaluated_statically = true; err.Clear(); return err; } Process *process = exe_ctx.GetProcessPtr(); if (!process || execution_policy == eExecutionPolicyNever) { err.SetErrorToGenericError(); if (execution_policy == eExecutionPolicyAlways) err.SetErrorString("Execution needed to run in the target, but the target can't be run"); else err.SetErrorStringWithFormat("Interpreting the expression locally failed: %s", interpreter_error.AsCString()); return err; } if (execution_policy != eExecutionPolicyNever && m_expr.NeedsValidation() && process) { if (!process->GetDynamicCheckers()) { DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions(); StreamString install_errors; if (!dynamic_checkers->Install(install_errors, exe_ctx)) { if (install_errors.GetString().empty()) err.SetErrorString ("couldn't install checkers, unknown error"); else err.SetErrorString (install_errors.GetString().c_str()); return err; } process->SetDynamicCheckers(dynamic_checkers); if (log) log->Printf("== [ClangUserExpression::Evaluate] Finished installing dynamic checkers =="); } IRDynamicChecks ir_dynamic_checks(*process->GetDynamicCheckers(), function_name.c_str()); if (!ir_dynamic_checks.runOnModule(*module)) { err.SetErrorToGenericError(); err.SetErrorString("Couldn't add dynamic checks to the expression"); return err; } } } // llvm will own this pointer when llvm::ExecutionEngine::createJIT is called // below so we don't need to free it. RecordingMemoryManager *jit_memory_manager = new RecordingMemoryManager(); std::string error_string; if (log) { std::string s; raw_string_ostream oss(s); module->print(oss, NULL); oss.flush(); log->Printf ("Module being sent to JIT: \n%s", s.c_str()); } EngineBuilder builder(module); builder.setEngineKind(EngineKind::JIT) .setErrorStr(&error_string) .setRelocationModel(llvm::Reloc::PIC_) .setJITMemoryManager(jit_memory_manager) .setOptLevel(CodeGenOpt::Less) .setAllocateGVsWithCode(true) .setCodeModel(CodeModel::Small) .setUseMCJIT(true); execution_engine.reset(builder.create()); if (!execution_engine.get()) { err.SetErrorToGenericError(); err.SetErrorStringWithFormat("Couldn't JIT the function: %s", error_string.c_str()); return err; } execution_engine->DisableLazyCompilation(); llvm::Function *function = module->getFunction (function_name.c_str()); // We don't actually need the function pointer here, this just forces it to get resolved. void *fun_ptr = execution_engine->getPointerToFunction(function); // Errors usually cause failures in the JIT, but if we're lucky we get here. if (!function) { err.SetErrorToGenericError(); err.SetErrorStringWithFormat("Couldn't find '%s' in the JITted module", function_name.c_str()); return err; } if (!fun_ptr) { err.SetErrorToGenericError(); err.SetErrorStringWithFormat("'%s' was in the JITted module but wasn't lowered", function_name.c_str()); return err; } m_jitted_functions.push_back (ClangExpressionParser::JittedFunction(function_name.c_str(), (lldb::addr_t)fun_ptr)); Process *process = exe_ctx.GetProcessPtr(); if (process == NULL) { err.SetErrorToGenericError(); err.SetErrorString("Couldn't write the JIT compiled code into the target because there is no target"); return err; } jit_memory_manager->CommitAllocations(*process); jit_memory_manager->ReportAllocations(*execution_engine); jit_memory_manager->WriteData(*process); std::vector<JittedFunction>::iterator pos, end = m_jitted_functions.end(); for (pos = m_jitted_functions.begin(); pos != end; pos++) { (*pos).m_remote_addr = jit_memory_manager->GetRemoteAddressForLocal ((*pos).m_local_addr); if (!(*pos).m_name.compare(function_name.c_str())) { RecordingMemoryManager::AddrRange func_range = jit_memory_manager->GetRemoteRangeForLocal((*pos).m_local_addr); func_end = func_range.first + func_range.second; func_addr = (*pos).m_remote_addr; } } if (log) { log->Printf("Code can be run in the target."); StreamString disassembly_stream; Error err = DisassembleFunction(disassembly_stream, exe_ctx, jit_memory_manager); if (!err.Success()) { log->Printf("Couldn't disassemble function : %s", err.AsCString("unknown error")); } else { log->Printf("Function disassembly:\n%s", disassembly_stream.GetData()); } } execution_engine.reset(); err.Clear(); return err; }