bool Disassembler::Disassemble ( Debugger &debugger, const ArchSpec &arch, const char *plugin_name, const char *flavor, const ExecutionContext &exe_ctx, const ConstString &name, Module *module, uint32_t num_instructions, uint32_t num_mixed_context_lines, uint32_t options, Stream &strm ) { SymbolContextList sc_list; if (name) { const bool include_symbols = true; const bool include_inlines = true; if (module) { module->FindFunctions (name, NULL, eFunctionNameTypeAuto, include_symbols, include_inlines, true, sc_list); } else if (exe_ctx.GetTargetPtr()) { exe_ctx.GetTargetPtr()->GetImages().FindFunctions (name, eFunctionNameTypeAuto, include_symbols, include_inlines, false, sc_list); } } if (sc_list.GetSize ()) { return Disassemble (debugger, arch, plugin_name, flavor, exe_ctx, sc_list, num_instructions, num_mixed_context_lines, options, strm); } return false; }
bool UnwindAssembly_x86::FirstNonPrologueInsn( AddressRange &func, const ExecutionContext &exe_ctx, Address &first_non_prologue_insn) { if (!func.GetBaseAddress().IsValid()) return false; Target *target = exe_ctx.GetTargetPtr(); if (target == nullptr) return false; if (m_assembly_inspection_engine == nullptr) return false; const bool prefer_file_cache = true; std::vector<uint8_t> function_text(func.GetByteSize()); Status error; if (target->ReadMemory(func.GetBaseAddress(), prefer_file_cache, function_text.data(), func.GetByteSize(), error) == func.GetByteSize()) { size_t offset; if (m_assembly_inspection_engine->FindFirstNonPrologueInstruction( function_text.data(), func.GetByteSize(), offset)) { first_non_prologue_insn = func.GetBaseAddress(); first_non_prologue_insn.Slide(offset); } return true; } return false; }
static void ResolveAddress (const ExecutionContext &exe_ctx, const Address &addr, Address &resolved_addr) { if (!addr.IsSectionOffset()) { // If we weren't passed in a section offset address range, // try and resolve it to something Target *target = exe_ctx.GetTargetPtr(); if (target) { if (target->GetSectionLoadList().IsEmpty()) { target->GetImages().ResolveFileAddress (addr.GetOffset(), resolved_addr); } else { target->GetSectionLoadList().ResolveLoadAddress (addr.GetOffset(), resolved_addr); } // We weren't able to resolve the address, just treat it as a // raw address if (resolved_addr.IsValid()) return; } } resolved_addr = addr; }
lldb::ExpressionResults GoUserExpression::DoExecute(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options, lldb::UserExpressionSP &shared_ptr_to_me, lldb::ExpressionVariableSP &result) { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy(); lldb::ExpressionResults execution_results = lldb::eExpressionSetupError; Process *process = exe_ctx.GetProcessPtr(); Target *target = exe_ctx.GetTargetPtr(); if (target == nullptr || process == nullptr || process->GetState() != lldb::eStateStopped) { if (execution_policy == eExecutionPolicyAlways) { if (log) log->Printf("== [GoUserExpression::Evaluate] Expression may not run, " "but is not constant =="); diagnostic_manager.PutCString(eDiagnosticSeverityError, "expression needed to run but couldn't"); return execution_results; } } m_interpreter->set_use_dynamic(options.GetUseDynamic()); ValueObjectSP result_val_sp = m_interpreter->Evaluate(exe_ctx); Error err = m_interpreter->error(); m_interpreter.reset(); if (!result_val_sp) { const char *error_cstr = err.AsCString(); if (error_cstr && error_cstr[0]) diagnostic_manager.PutCString(eDiagnosticSeverityError, error_cstr); else diagnostic_manager.PutCString(eDiagnosticSeverityError, "expression can't be interpreted or run"); return lldb::eExpressionDiscarded; } result.reset(new ExpressionVariable(ExpressionVariable::eKindGo)); result->m_live_sp = result->m_frozen_sp = result_val_sp; result->m_flags |= ExpressionVariable::EVIsProgramReference; PersistentExpressionState *pv = target->GetPersistentExpressionStateForLanguage(eLanguageTypeGo); if (pv != nullptr) { result->SetName(pv->GetNextPersistentVariableName()); pv->AddVariable(result); } return lldb::eExpressionCompleted; }
lldb::ExpressionResults UserExpression::Execute(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options, lldb::UserExpressionSP &shared_ptr_to_me, lldb::ExpressionVariableSP &result_var) { lldb::ExpressionResults expr_result = DoExecute(diagnostic_manager, exe_ctx, options, shared_ptr_to_me, result_var); Target *target = exe_ctx.GetTargetPtr(); if (options.GetResultIsInternal() && result_var && target) { target->GetPersistentExpressionStateForLanguage(m_language)->RemovePersistentVariable (result_var); } return expr_result; }
bool ClangUserExpression::SetupPersistentState(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx) { if (Target *target = exe_ctx.GetTargetPtr()) { if (PersistentExpressionState *persistent_state = target->GetPersistentExpressionStateForLanguage( lldb::eLanguageTypeC)) { m_result_delegate.RegisterPersistentState(persistent_state); } else { diagnostic_manager.PutString( eDiagnosticSeverityError, "couldn't start parsing (no persistent data)"); return false; } } else { diagnostic_manager.PutString(eDiagnosticSeverityError, "error: couldn't start parsing (no target)"); return false; } return true; }
bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, lldb_private::ExecutionPolicy execution_policy, bool keep_result_in_memory, bool generate_debug_info) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); if (!PrepareForParsing(diagnostic_manager, exe_ctx)) 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) { diagnostic_manager.PutString(eDiagnosticSeverityError, "invalid target"); return false; } ////////////////////////// // Parse the expression // m_materializer_ap.reset(new Materializer()); ResetDeclMap(exe_ctx, m_result_delegate, keep_result_in_memory); OnExit on_exit([this]() { ResetDeclMap(); }); if (!DeclMap()->WillParse(exe_ctx, m_materializer_ap.get())) { diagnostic_manager.PutString( eDiagnosticSeverityError, "current process state is unsuitable for expression parsing"); return false; } if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) { DeclMap()->SetLookupsEnabled(true); } Process *process = exe_ctx.GetProcessPtr(); ExecutionContextScope *exe_scope = process; if (!exe_scope) exe_scope = exe_ctx.GetTargetPtr(); // We use a shared pointer here so we can use the original parser - if it // succeeds or the rewrite parser we might make if it fails. But the // parser_sp will never be empty. ClangExpressionParser parser(exe_scope, *this, generate_debug_info); unsigned num_errors = parser.Parse(diagnostic_manager); // Check here for FixItHints. If there are any try to apply the fixits and // set the fixed text in m_fixed_text before returning an error. if (num_errors) { if (diagnostic_manager.HasFixIts()) { if (parser.RewriteExpression(diagnostic_manager)) { size_t fixed_start; size_t fixed_end; const std::string &fixed_expression = diagnostic_manager.GetFixedExpression(); if (ExpressionSourceCode::GetOriginalBodyBounds( fixed_expression, m_expr_lang, fixed_start, fixed_end)) m_fixed_text = fixed_expression.substr(fixed_start, fixed_end - fixed_start); } } return false; } ////////////////////////////////////////////////////////////////////////////////////////// // Prepare the output of the parser for execution, evaluating it statically // if possible // { Status jit_error = parser.PrepareForExecution( m_jit_start_addr, m_jit_end_addr, m_execution_unit_sp, exe_ctx, m_can_interpret, execution_policy); if (!jit_error.Success()) { const char *error_cstr = jit_error.AsCString(); if (error_cstr && error_cstr[0]) diagnostic_manager.PutString(eDiagnosticSeverityError, error_cstr); else diagnostic_manager.PutString(eDiagnosticSeverityError, "expression can't be interpreted or run"); return false; } } if (exe_ctx.GetProcessPtr() && execution_policy == eExecutionPolicyTopLevel) { Status static_init_error = parser.RunStaticInitializers(m_execution_unit_sp, exe_ctx); if (!static_init_error.Success()) { const char *error_cstr = static_init_error.AsCString(); if (error_cstr && error_cstr[0]) diagnostic_manager.Printf(eDiagnosticSeverityError, "couldn't run static initializers: %s\n", error_cstr); else diagnostic_manager.PutString(eDiagnosticSeverityError, "couldn't run static initializers\n"); return false; } } if (m_execution_unit_sp) { bool register_execution_unit = false; if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) { register_execution_unit = true; } // If there is more than one external function in the execution unit, it // needs to keep living even if it's not top level, because the result // could refer to that function. if (m_execution_unit_sp->GetJittedFunctions().size() > 1) { register_execution_unit = true; } if (register_execution_unit) { llvm::cast<PersistentExpressionState>( exe_ctx.GetTargetPtr()->GetPersistentExpressionStateForLanguage( m_language)) ->RegisterExecutionUnit(m_execution_unit_sp); } } 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); } } if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS) m_jit_process_wp = lldb::ProcessWP(process->shared_from_this()); return true; }
//------------------------------------------------------------------ /// Install the utility function into a process /// /// @param[in] error_stream /// A stream to print parse errors and warnings to. /// /// @param[in] exe_ctx /// The execution context to install the utility function to. /// /// @return /// True on success (no errors); false otherwise. //------------------------------------------------------------------ bool ClangUtilityFunction::Install (Stream &error_stream, ExecutionContext &exe_ctx) { lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); if (m_jit_start_addr != LLDB_INVALID_ADDRESS) { error_stream.PutCString("error: already installed\n"); return false; } //////////////////////////////////// // Set up the target and compiler // Target *target = exe_ctx.GetTargetPtr(); if (!target) { error_stream.PutCString ("error: invalid target\n"); return false; } Process *process = exe_ctx.GetProcessPtr(); if (!process) { error_stream.PutCString ("error: invalid process\n"); return false; } ////////////////////////// // Parse the expression // bool keep_result_in_memory = false; m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx)); m_data_allocator.reset(new ProcessDataAllocator(*process)); if (!m_expr_decl_map->WillParse(exe_ctx)) { error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n"); return false; } ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this); 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(); return false; } ////////////////////////////////// // JIT the output of the parser // lldb::ClangExpressionVariableSP const_result; bool evaluated_statically = false; // should stay that way Error jit_error = parser.PrepareForExecution (m_jit_alloc, m_jit_start_addr, m_jit_end_addr, exe_ctx, m_data_allocator.get(), evaluated_statically, const_result, eExecutionPolicyAlways); if (log) { StreamString dump_string; m_data_allocator->Dump(dump_string); log->Printf("Data buffer contents:\n%s", dump_string.GetString().c_str()); } if (m_jit_start_addr != LLDB_INVALID_ADDRESS) m_jit_process_wp = lldb::ProcessWP(process->shared_from_this()); #if 0 // jingham: look here StreamFile logfile ("/tmp/exprs.txt", "a"); logfile.Printf ("0x%16.16" PRIx64 ": func = %s, source =\n%s\n", m_jit_start_addr, m_function_name.c_str(), m_function_text.c_str()); #endif m_expr_decl_map->DidParse(); m_expr_decl_map.reset(); if (jit_error.Success()) { return true; } else { const char *error_cstr = jit_error.AsCString(); if (error_cstr && error_cstr[0]) error_stream.Printf ("error: %s\n", error_cstr); else error_stream.Printf ("error: expression can't be interpreted or run\n"); return false; } }
void ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); 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) { if (log) 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) log->Printf(" [CUE::SC] Null function block"); return; } clang::DeclContext *decl_context = function_block->GetClangDeclContext(); if (!decl_context) { if (log) 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()) { 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->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) || !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; } } else if (clang::FunctionDecl *function_decl = llvm::dyn_cast<clang::FunctionDecl>(decl_context)) { // We might also have a function that said in the debug information that it captured an // 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()) { lldb::LanguageType language = metadata->GetObjectPtrLanguage(); if (language == lldb::eLanguageTypeC_plus_plus) { 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)) { err.SetErrorString(thisErrorString); return; } } m_cplusplus = true; m_needs_object_ptr = true; } else if (language == lldb::eLanguageTypeObjC) { 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)) { 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; } else if (self_clang_type.IsObjCObjectPointerType()) { m_objectivec = true; m_needs_object_ptr = true; } else { err.SetErrorString(selfErrorString); return; } } else { m_objectivec = true; m_needs_object_ptr = true; } } } } }
//------------------------------------------------------------------ /// Install the utility function into a process /// /// @param[in] error_stream /// A stream to print parse errors and warnings to. /// /// @param[in] exe_ctx /// The execution context to install the utility function to. /// /// @return /// True on success (no errors); false otherwise. //------------------------------------------------------------------ bool ClangUtilityFunction::Install (Stream &error_stream, ExecutionContext &exe_ctx) { if (m_jit_start_addr != LLDB_INVALID_ADDRESS) { error_stream.PutCString("error: already installed\n"); return false; } //////////////////////////////////// // Set up the target and compiler // Target *target = exe_ctx.GetTargetPtr(); if (!target) { error_stream.PutCString ("error: invalid target\n"); return false; } Process *process = exe_ctx.GetProcessPtr(); if (!process) { error_stream.PutCString ("error: invalid process\n"); return false; } ////////////////////////// // Parse the expression // bool keep_result_in_memory = false; m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx)); if (!m_expr_decl_map->WillParse(exe_ctx, NULL)) { error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n"); return false; } ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this); 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(); return false; } ////////////////////////////////// // JIT the output of the parser // bool can_interpret = false; // should stay that way Error jit_error = parser.PrepareForExecution (m_jit_start_addr, m_jit_end_addr, m_execution_unit_ap, exe_ctx, can_interpret, eExecutionPolicyAlways); if (m_jit_start_addr != LLDB_INVALID_ADDRESS) m_jit_process_wp = lldb::ProcessWP(process->shared_from_this()); #if 0 // jingham: look here StreamFile logfile ("/tmp/exprs.txt", "a"); logfile.Printf ("0x%16.16" PRIx64 ": func = %s, source =\n%s\n", m_jit_start_addr, m_function_name.c_str(), m_function_text.c_str()); #endif m_expr_decl_map->DidParse(); m_expr_decl_map.reset(); if (jit_error.Success()) { return true; } else { const char *error_cstr = jit_error.AsCString(); if (error_cstr && error_cstr[0]) error_stream.Printf ("error: %s\n", error_cstr); else error_stream.Printf ("error: expression can't be interpreted or run\n"); return false; } }
lldb_private::Error ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr, lldb::addr_t &func_end, lldb::IRExecutionUnitSP &execution_unit_sp, ExecutionContext &exe_ctx, bool &can_interpret, ExecutionPolicy execution_policy) { func_addr = LLDB_INVALID_ADDRESS; func_end = LLDB_INVALID_ADDRESS; Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); lldb_private::Error err; std::unique_ptr<llvm::Module> llvm_module_ap (m_code_generator->ReleaseModule()); if (!llvm_module_ap.get()) { err.SetErrorToGenericError(); err.SetErrorString("IR doesn't contain a module"); return err; } ConstString function_name; if (execution_policy != eExecutionPolicyTopLevel) { // Find the actual name of the function (it's often mangled somehow) if (!FindFunctionInModule(function_name, llvm_module_ap.get(), 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.AsCString(), m_expr.FunctionName()); } } SymbolContext sc; if (lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP()) { sc = frame_sp->GetSymbolContext(lldb::eSymbolContextEverything); } else if (lldb::TargetSP target_sp = exe_ctx.GetTargetSP()) { sc.target_sp = target_sp; } LLVMUserExpression::IRPasses custom_passes; { auto lang = m_expr.Language(); if (log) log->Printf("%s - Currrent expression language is %s\n", __FUNCTION__, Language::GetNameForLanguageType(lang)); if (lang != lldb::eLanguageTypeUnknown) { auto runtime = exe_ctx.GetProcessSP()->GetLanguageRuntime(lang); if (runtime) runtime->GetIRPasses(custom_passes); } } if (custom_passes.EarlyPasses) { if (log) log->Printf("%s - Running Early IR Passes from LanguageRuntime on expression module '%s'", __FUNCTION__, m_expr.FunctionName()); custom_passes.EarlyPasses->run(*llvm_module_ap); } execution_unit_sp.reset(new IRExecutionUnit (m_llvm_context, // handed off here llvm_module_ap, // handed off here function_name, exe_ctx.GetTargetSP(), sc, m_compiler->getTargetOpts().Features)); ClangExpressionHelper *type_system_helper = dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper()); ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap(); // result can be NULL if (decl_map) { Stream *error_stream = NULL; Target *target = exe_ctx.GetTargetPtr(); if (target) error_stream = target->GetDebugger().GetErrorFile().get(); IRForTarget ir_for_target(decl_map, m_expr.NeedsVariableResolution(), *execution_unit_sp, error_stream, function_name.AsCString()); bool ir_can_run = ir_for_target.runOnModule(*execution_unit_sp->GetModule()); Process *process = exe_ctx.GetProcessPtr(); if (execution_policy != eExecutionPolicyAlways && execution_policy != eExecutionPolicyTopLevel) { lldb_private::Error interpret_error; bool interpret_function_calls = !process ? false : process->CanInterpretFunctionCalls(); can_interpret = IRInterpreter::CanInterpret(*execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(), interpret_error, interpret_function_calls); if (!can_interpret && execution_policy == eExecutionPolicyNever) { err.SetErrorStringWithFormat("Can't run the expression locally: %s", interpret_error.AsCString()); return err; } } if (!ir_can_run) { err.SetErrorString("The expression could not be prepared to run in the target"); return err; } if (!process && execution_policy == eExecutionPolicyAlways) { err.SetErrorString("Expression needed to run in the target, but the target can't be run"); return err; } if (!process && execution_policy == eExecutionPolicyTopLevel) { err.SetErrorString( "Top-level code needs to be inserted into a runnable target, but the target can't be run"); return err; } if (execution_policy == eExecutionPolicyAlways || (execution_policy != eExecutionPolicyTopLevel && !can_interpret)) { if (m_expr.NeedsValidation() && process) { if (!process->GetDynamicCheckers()) { DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions(); DiagnosticManager install_diagnostics; if (!dynamic_checkers->Install(install_diagnostics, exe_ctx)) { if (install_diagnostics.Diagnostics().size()) err.SetErrorString("couldn't install checkers, unknown error"); else err.SetErrorString(install_diagnostics.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.AsCString()); llvm::Module *module = execution_unit_sp->GetModule(); if (!module || !ir_dynamic_checks.runOnModule(*module)) { err.SetErrorToGenericError(); err.SetErrorString("Couldn't add dynamic checks to the expression"); return err; } if (custom_passes.LatePasses) { if (log) log->Printf("%s - Running Late IR Passes from LanguageRuntime on expression module '%s'", __FUNCTION__, m_expr.FunctionName()); custom_passes.LatePasses->run(*module); } } } if (execution_policy == eExecutionPolicyAlways || execution_policy == eExecutionPolicyTopLevel || !can_interpret) { execution_unit_sp->GetRunnableInfo(err, func_addr, func_end); } } else { execution_unit_sp->GetRunnableInfo(err, func_addr, func_end); } return err; }
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)); 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()); if (!ir_for_target.runOnModule(*module)) { err.SetErrorToGenericError(); err.SetErrorString("Couldn't prepare the expression for execution in the target"); return err; } if (execution_policy != eExecutionPolicyAlways && ir_for_target.interpretSuccess()) { evaluated_statically = true; err.Clear(); return err; } Process *process = exe_ctx.GetProcessPtr(); if (!process || execution_policy == eExecutionPolicyNever) { err.SetErrorToGenericError(); err.SetErrorString("Execution needed to run in the target, but the target can't be run"); 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()); } #if defined (USE_STANDARD_JIT) m_execution_engine.reset(llvm::ExecutionEngine::createJIT (module, &error_string, jit_memory_manager, CodeGenOpt::Less, true, Reloc::Default, CodeModel::Small)); #else 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); m_execution_engine.reset(builder.create()); #endif if (!m_execution_engine.get()) { err.SetErrorToGenericError(); err.SetErrorStringWithFormat("Couldn't JIT the function: %s", error_string.c_str()); return err; } m_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 = m_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; } // Look over the regions allocated for the function compiled. The JIT // tries to allocate the functions & stubs close together, so we should try to // write them that way too... // For now I only write functions with no stubs, globals, exception tables, // etc. So I only need to write the functions. size_t alloc_size = 0; std::map<uint8_t *, uint8_t *>::iterator fun_pos = jit_memory_manager->m_functions.begin(); std::map<uint8_t *, uint8_t *>::iterator fun_end = jit_memory_manager->m_functions.end(); for (; fun_pos != fun_end; ++fun_pos) { size_t mem_size = fun_pos->second - fun_pos->first; if (log) log->Printf ("JIT memory: [%p - %p) size = %zu", fun_pos->first, fun_pos->second, mem_size); alloc_size += mem_size; } Error alloc_error; func_allocation_addr = process->AllocateMemory (alloc_size, lldb::ePermissionsReadable|lldb::ePermissionsExecutable, alloc_error); if (func_allocation_addr == LLDB_INVALID_ADDRESS) { err.SetErrorToGenericError(); err.SetErrorStringWithFormat("Couldn't allocate memory for the JITted function: %s", alloc_error.AsCString("unknown error")); return err; } lldb::addr_t cursor = func_allocation_addr; for (fun_pos = jit_memory_manager->m_functions.begin(); fun_pos != fun_end; fun_pos++) { lldb::addr_t lstart = (lldb::addr_t) (*fun_pos).first; lldb::addr_t lend = (lldb::addr_t) (*fun_pos).second; size_t size = lend - lstart; Error write_error; if (process->WriteMemory(cursor, (void *) lstart, size, write_error) != size) { err.SetErrorToGenericError(); err.SetErrorStringWithFormat("Couldn't copy JIT code for function into the target: %s", write_error.AsCString("unknown error")); return err; } jit_memory_manager->AddToLocalToRemoteMap (lstart, size, cursor); cursor += size; } 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())) { func_end = jit_memory_manager->GetRemoteRangeForLocal ((*pos).m_local_addr).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()); } } err.Clear(); return err; }
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; } }
bool FunctionCaller::WriteFunctionArguments( ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, ValueList &arg_values, DiagnosticManager &diagnostic_manager) { // All the information to reconstruct the struct is provided by the // StructExtractor. if (!m_struct_valid) { diagnostic_manager.PutString(eDiagnosticSeverityError, "Argument information was not correctly " "parsed, so the function cannot be called."); return false; } Status error; lldb::ExpressionResults return_value = lldb::eExpressionSetupError; Process *process = exe_ctx.GetProcessPtr(); if (process == NULL) return return_value; lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock()); if (process != jit_process_sp.get()) return false; if (args_addr_ref == LLDB_INVALID_ADDRESS) { args_addr_ref = process->AllocateMemory( m_struct_size, lldb::ePermissionsReadable | lldb::ePermissionsWritable, error); if (args_addr_ref == LLDB_INVALID_ADDRESS) return false; m_wrapper_args_addrs.push_back(args_addr_ref); } else { // Make sure this is an address that we've already handed out. if (find(m_wrapper_args_addrs.begin(), m_wrapper_args_addrs.end(), args_addr_ref) == m_wrapper_args_addrs.end()) { return false; } } // TODO: verify fun_addr needs to be a callable address Scalar fun_addr( m_function_addr.GetCallableLoadAddress(exe_ctx.GetTargetPtr())); uint64_t first_offset = m_member_offsets[0]; process->WriteScalarToMemory(args_addr_ref + first_offset, fun_addr, process->GetAddressByteSize(), error); // FIXME: We will need to extend this for Variadic functions. Status value_error; size_t num_args = arg_values.GetSize(); if (num_args != m_arg_values.GetSize()) { diagnostic_manager.Printf( eDiagnosticSeverityError, "Wrong number of arguments - was: %" PRIu64 " should be: %" PRIu64 "", (uint64_t)num_args, (uint64_t)m_arg_values.GetSize()); return false; } for (size_t i = 0; i < num_args; i++) { // FIXME: We should sanity check sizes. uint64_t offset = m_member_offsets[i + 1]; // Clang sizes are in bytes. Value *arg_value = arg_values.GetValueAtIndex(i); // FIXME: For now just do scalars: // Special case: if it's a pointer, don't do anything (the ABI supports // passing cstrings) if (arg_value->GetValueType() == Value::eValueTypeHostAddress && arg_value->GetContextType() == Value::eContextTypeInvalid && arg_value->GetCompilerType().IsPointerType()) continue; const Scalar &arg_scalar = arg_value->ResolveValue(&exe_ctx); if (!process->WriteScalarToMemory(args_addr_ref + offset, arg_scalar, arg_scalar.GetByteSize(), error)) return false; } return true; }
bool ClangUserExpression::Complete(ExecutionContext &exe_ctx, CompletionRequest &request, unsigned complete_pos) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); // We don't want any visible feedback when completing an expression. Mostly // because the results we get from an incomplete invocation are probably not // correct. DiagnosticManager diagnostic_manager; if (!PrepareForParsing(diagnostic_manager, exe_ctx)) return false; if (log) log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str()); ////////////////////////// // Parse the expression // m_materializer_ap.reset(new Materializer()); ResetDeclMap(exe_ctx, m_result_delegate, /*keep result in memory*/ true); OnExit on_exit([this]() { ResetDeclMap(); }); if (!DeclMap()->WillParse(exe_ctx, m_materializer_ap.get())) { diagnostic_manager.PutString( eDiagnosticSeverityError, "current process state is unsuitable for expression parsing"); return false; } if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) { DeclMap()->SetLookupsEnabled(true); } Process *process = exe_ctx.GetProcessPtr(); ExecutionContextScope *exe_scope = process; if (!exe_scope) exe_scope = exe_ctx.GetTargetPtr(); ClangExpressionParser parser(exe_scope, *this, false); // We have to find the source code location where the user text is inside // the transformed expression code. When creating the transformed text, we // already stored the absolute position in the m_transformed_text string. The // only thing left to do is to transform it into the line:column format that // Clang expects. // The line and column of the user expression inside the transformed source // code. unsigned user_expr_line, user_expr_column; if (m_user_expression_start_pos.hasValue()) AbsPosToLineColumnPos(*m_user_expression_start_pos, m_transformed_text, user_expr_line, user_expr_column); else return false; // The actual column where we have to complete is the start column of the // user expression + the offset inside the user code that we were given. const unsigned completion_column = user_expr_column + complete_pos; parser.Complete(request, user_expr_line, completion_column, complete_pos); return true; }
//------------------------------------------------------------------ /// Install the utility function into a process /// /// @param[in] diagnostic_manager /// A diagnostic manager to report errors and warnings to. /// /// @param[in] exe_ctx /// The execution context to install the utility function to. /// /// @return /// True on success (no errors); false otherwise. //------------------------------------------------------------------ bool ClangUtilityFunction::Install(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx) { if (m_jit_start_addr != LLDB_INVALID_ADDRESS) { diagnostic_manager.PutCString(eDiagnosticSeverityWarning, "already installed"); return false; } //////////////////////////////////// // Set up the target and compiler // Target *target = exe_ctx.GetTargetPtr(); if (!target) { diagnostic_manager.PutCString(eDiagnosticSeverityError, "invalid target"); return false; } Process *process = exe_ctx.GetProcessPtr(); if (!process) { diagnostic_manager.PutCString(eDiagnosticSeverityError, "invalid process"); return false; } ////////////////////////// // Parse the expression // bool keep_result_in_memory = false; ResetDeclMap(exe_ctx, keep_result_in_memory); if (!DeclMap()->WillParse(exe_ctx, NULL)) { diagnostic_manager.PutCString( eDiagnosticSeverityError, "current process state is unsuitable for expression parsing"); return false; } const bool generate_debug_info = true; ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this, generate_debug_info); unsigned num_errors = parser.Parse(diagnostic_manager); if (num_errors) { ResetDeclMap(); return false; } ////////////////////////////////// // JIT the output of the parser // bool can_interpret = false; // should stay that way Error jit_error = parser.PrepareForExecution( m_jit_start_addr, m_jit_end_addr, m_execution_unit_sp, exe_ctx, can_interpret, eExecutionPolicyAlways); if (m_jit_start_addr != LLDB_INVALID_ADDRESS) { m_jit_process_wp = process->shared_from_this(); if (parser.GetGenerateDebugInfo()) m_execution_unit_sp->CreateJITModule(FunctionName()); } #if 0 // jingham: look here StreamFile logfile ("/tmp/exprs.txt", "a"); logfile.Printf ("0x%16.16" PRIx64 ": func = %s, source =\n%s\n", m_jit_start_addr, m_function_name.c_str(), m_function_text.c_str()); #endif DeclMap()->DidParse(); ResetDeclMap(); if (jit_error.Success()) { return true; } else { const char *error_cstr = jit_error.AsCString(); if (error_cstr && error_cstr[0]) { diagnostic_manager.Printf(eDiagnosticSeverityError, "%s", error_cstr); } else { diagnostic_manager.PutCString(eDiagnosticSeverityError, "expression can't be interpreted or run"); } return false; } }
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; }
bool ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, Address function_address, ValueList &arg_values, Stream &errors) { // All the information to reconstruct the struct is provided by the // StructExtractor. if (!m_struct_valid) { errors.Printf("Argument information was not correctly parsed, so the function cannot be called."); return false; } Error error; using namespace clang; ExecutionResults return_value = eExecutionSetupError; Process *process = exe_ctx.GetProcessPtr(); if (process == NULL) return return_value; if (process != m_jit_process_sp.get()) return false; if (args_addr_ref == LLDB_INVALID_ADDRESS) { args_addr_ref = process->AllocateMemory(m_struct_size, lldb::ePermissionsReadable|lldb::ePermissionsWritable, error); if (args_addr_ref == LLDB_INVALID_ADDRESS) return false; m_wrapper_args_addrs.push_back (args_addr_ref); } else { // Make sure this is an address that we've already handed out. if (find (m_wrapper_args_addrs.begin(), m_wrapper_args_addrs.end(), args_addr_ref) == m_wrapper_args_addrs.end()) { return false; } } // TODO: verify fun_addr needs to be a callable address Scalar fun_addr (function_address.GetCallableLoadAddress(exe_ctx.GetTargetPtr())); int first_offset = m_member_offsets[0]; process->WriteScalarToMemory(args_addr_ref + first_offset, fun_addr, process->GetAddressByteSize(), error); // FIXME: We will need to extend this for Variadic functions. Error value_error; size_t num_args = arg_values.GetSize(); if (num_args != m_arg_values.GetSize()) { errors.Printf ("Wrong number of arguments - was: %lu should be: %lu", num_args, m_arg_values.GetSize()); return false; } for (size_t i = 0; i < num_args; i++) { // FIXME: We should sanity check sizes. int offset = m_member_offsets[i+1]; // Clang sizes are in bytes. Value *arg_value = arg_values.GetValueAtIndex(i); // FIXME: For now just do scalars: // Special case: if it's a pointer, don't do anything (the ABI supports passing cstrings) if (arg_value->GetValueType() == Value::eValueTypeHostAddress && arg_value->GetContextType() == Value::eContextTypeClangType && ClangASTContext::IsPointerType(arg_value->GetClangType())) continue; const Scalar &arg_scalar = arg_value->ResolveValue(&exe_ctx, m_clang_ast_context->getASTContext()); if (!process->WriteScalarToMemory(args_addr_ref + offset, arg_scalar, arg_scalar.GetByteSize(), error)) return false; } return true; }
Error ClangExpressionParser::DisassembleFunction (Stream &stream, ExecutionContext &exe_ctx, RecordingMemoryManager *jit_memory_manager) { lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); const char *name = m_expr.FunctionName(); Error ret; ret.Clear(); lldb::addr_t func_local_addr = LLDB_INVALID_ADDRESS; lldb::addr_t func_remote_addr = LLDB_INVALID_ADDRESS; std::vector<JittedFunction>::iterator pos, end = m_jitted_functions.end(); for (pos = m_jitted_functions.begin(); pos < end; pos++) { if (strstr(pos->m_name.c_str(), name)) { func_local_addr = pos->m_local_addr; func_remote_addr = pos->m_remote_addr; } } if (func_local_addr == LLDB_INVALID_ADDRESS) { ret.SetErrorToGenericError(); ret.SetErrorStringWithFormat("Couldn't find function %s for disassembly", name); return ret; } if (log) log->Printf("Found function, has local address 0x%llx and remote address 0x%llx", (uint64_t)func_local_addr, (uint64_t)func_remote_addr); std::pair <lldb::addr_t, lldb::addr_t> func_range; func_range = jit_memory_manager->GetRemoteRangeForLocal(func_local_addr); if (func_range.first == 0 && func_range.second == 0) { ret.SetErrorToGenericError(); ret.SetErrorStringWithFormat("Couldn't find code range for function %s", name); return ret; } if (log) log->Printf("Function's code range is [0x%llx+0x%llx]", func_range.first, func_range.second); Target *target = exe_ctx.GetTargetPtr(); if (!target) { ret.SetErrorToGenericError(); ret.SetErrorString("Couldn't find the target"); } lldb::DataBufferSP buffer_sp(new DataBufferHeap(func_range.second, 0)); Process *process = exe_ctx.GetProcessPtr(); Error err; process->ReadMemory(func_remote_addr, buffer_sp->GetBytes(), buffer_sp->GetByteSize(), err); if (!err.Success()) { ret.SetErrorToGenericError(); ret.SetErrorStringWithFormat("Couldn't read from process: %s", err.AsCString("unknown error")); return ret; } ArchSpec arch(target->GetArchitecture()); Disassembler *disassembler = Disassembler::FindPlugin(arch, NULL); if (disassembler == NULL) { ret.SetErrorToGenericError(); ret.SetErrorStringWithFormat("Unable to find disassembler plug-in for %s architecture.", arch.GetArchitectureName()); return ret; } if (!process) { ret.SetErrorToGenericError(); ret.SetErrorString("Couldn't find the process"); return ret; } DataExtractor extractor(buffer_sp, process->GetByteOrder(), target->GetArchitecture().GetAddressByteSize()); if (log) { log->Printf("Function data has contents:"); extractor.PutToLog (log.get(), 0, extractor.GetByteSize(), func_remote_addr, 16, DataExtractor::TypeUInt8); } disassembler->DecodeInstructions (Address (func_remote_addr), extractor, 0, UINT32_MAX, false); InstructionList &instruction_list = disassembler->GetInstructionList(); const uint32_t max_opcode_byte_size = instruction_list.GetMaxOpcocdeByteSize(); for (uint32_t instruction_index = 0, num_instructions = instruction_list.GetSize(); instruction_index < num_instructions; ++instruction_index) { Instruction *instruction = instruction_list.GetInstructionAtIndex(instruction_index).get(); instruction->Dump (&stream, max_opcode_byte_size, true, true, &exe_ctx); stream.PutChar('\n'); } return ret; }
bool ClangUserExpression::Parse (Stream &error_stream, ExecutionContext &exe_ctx, lldb_private::ExecutionPolicy execution_policy, 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, 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(); } 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, 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_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) m_jit_process_wp = lldb::ProcessWP(process->shared_from_this()); return true; } else { const char *error_cstr = jit_error.AsCString(); if (error_cstr && error_cstr[0]) error_stream.Printf ("error: %s\n", error_cstr); else error_stream.Printf ("error: expression can't be interpreted or run\n"); return false; } }
lldb::ExpressionResults UserExpression::Evaluate (ExecutionContext &exe_ctx, const EvaluateExpressionOptions& options, const char *expr_cstr, const char *expr_prefix, lldb::ValueObjectSP &result_valobj_sp, Error &error, uint32_t line_offset, lldb::ModuleSP *jit_module_sp_ptr) { Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy(); lldb::LanguageType language = options.GetLanguage(); const ResultType desired_type = options.DoesCoerceToId() ? UserExpression::eResultTypeId : UserExpression::eResultTypeAny; lldb::ExpressionResults execution_results = lldb::eExpressionSetupError; Target *target = exe_ctx.GetTargetPtr(); if (!target) { if (log) log->Printf("== [UserExpression::Evaluate] Passed a NULL target, can't run expressions."); return lldb::eExpressionSetupError; } Process *process = exe_ctx.GetProcessPtr(); if (process == NULL || process->GetState() != lldb::eStateStopped) { if (execution_policy == eExecutionPolicyAlways) { if (log) log->Printf("== [UserExpression::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; const char *full_prefix = NULL; const char *option_prefix = options.GetPrefix(); std::string full_prefix_storage; if (expr_prefix && option_prefix) { full_prefix_storage.assign(expr_prefix); full_prefix_storage.append(option_prefix); if (!full_prefix_storage.empty()) full_prefix = full_prefix_storage.c_str(); } else if (expr_prefix) full_prefix = expr_prefix; else full_prefix = option_prefix; // If the language was not specified in the expression command, // set it to the language in the target's properties if // specified, else default to the langage for the frame. if (language == lldb::eLanguageTypeUnknown) { if (target->GetLanguage() != lldb::eLanguageTypeUnknown) language = target->GetLanguage(); else if (StackFrame *frame = exe_ctx.GetFramePtr()) language = frame->GetLanguage(); } // If the language was not specified in the expression command, // set it to the language in the target's properties if // specified, else default to the langage for the frame. if (language == lldb::eLanguageTypeUnknown) { if (target->GetLanguage() != lldb::eLanguageTypeUnknown) language = target->GetLanguage(); else if (StackFrame *frame = exe_ctx.GetFramePtr()) language = frame->GetLanguage(); } lldb::UserExpressionSP user_expression_sp(target->GetUserExpressionForLanguage (expr_cstr, full_prefix, language, desired_type, options, error)); if (error.Fail()) { if (log) log->Printf ("== [UserExpression::Evaluate] Getting expression: %s ==", error.AsCString()); return lldb::eExpressionSetupError; } StreamString error_stream; if (log) log->Printf("== [UserExpression::Evaluate] Parsing expression %s ==", expr_cstr); const bool keep_expression_in_memory = true; 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, 0)) { execution_results = lldb::eExpressionParseError; if (error_stream.GetString().empty()) error.SetExpressionError (execution_results, "expression failed to parse, unknown error"); else error.SetExpressionError (execution_results, error_stream.GetString().c_str()); } else { // If a pointer to a lldb::ModuleSP was passed in, return the JIT'ed module if one was created if (jit_module_sp_ptr) *jit_module_sp_ptr = user_expression_sp->GetJITModule(); lldb::ExpressionVariableSP expr_result; if (execution_policy == eExecutionPolicyNever && !user_expression_sp->CanInterpret()) { if (log) log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant =="); if (error_stream.GetString().empty()) 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("== [UserExpression::Evaluate] Executing expression =="); execution_results = user_expression_sp->Execute (error_stream, exe_ctx, options, user_expression_sp, expr_result); if (options.GetResultIsInternal() && expr_result && process) { process->GetTarget().GetPersistentExpressionStateForLanguage(language)->RemovePersistentVariable (expr_result); } if (execution_results != lldb::eExpressionCompleted) { if (log) log->Printf("== [UserExpression::Evaluate] Execution completed abnormally =="); if (error_stream.GetString().empty()) error.SetExpressionError (execution_results, "expression failed to execute, unknown error"); else error.SetExpressionError (execution_results, error_stream.GetString().c_str()); } else { if (expr_result) { result_valobj_sp = expr_result->GetValueObject(); if (log) log->Printf("== [UserExpression::Evaluate] Execution completed normally with result %s ==", result_valobj_sp->GetValueAsCString()); } else { if (log) log->Printf("== [UserExpression::Evaluate] Execution completed normally with no result =="); error.SetError(UserExpression::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); } return execution_results; }
Error ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr, lldb::addr_t &func_end, std::shared_ptr<IRExecutionUnit> &execution_unit_sp, ExecutionContext &exe_ctx, bool &can_interpret, ExecutionPolicy execution_policy) { func_addr = LLDB_INVALID_ADDRESS; func_end = LLDB_INVALID_ADDRESS; Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); Error err; std::unique_ptr<llvm::Module> llvm_module_ap (m_code_generator->ReleaseModule()); if (!llvm_module_ap.get()) { err.SetErrorToGenericError(); err.SetErrorString("IR doesn't contain a module"); return err; } // Find the actual name of the function (it's often mangled somehow) ConstString function_name; if (!FindFunctionInModule(function_name, llvm_module_ap.get(), 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.AsCString(), m_expr.FunctionName()); } execution_unit_sp.reset(new IRExecutionUnit (m_llvm_context, // handed off here llvm_module_ap, // handed off here function_name, exe_ctx.GetTargetSP(), m_compiler->getTargetOpts().Features)); 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().GetErrorFile().get(); IRForTarget ir_for_target(decl_map, m_expr.NeedsVariableResolution(), *execution_unit_sp, error_stream, function_name.AsCString()); bool ir_can_run = ir_for_target.runOnModule(*execution_unit_sp->GetModule()); Error interpret_error; can_interpret = IRInterpreter::CanInterpret(*execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(), interpret_error); Process *process = exe_ctx.GetProcessPtr(); if (!ir_can_run) { err.SetErrorString("The expression could not be prepared to run in the target"); return err; } if (!can_interpret && execution_policy == eExecutionPolicyNever) { err.SetErrorStringWithFormat("Can't run the expression locally: %s", interpret_error.AsCString()); return err; } if (!process && execution_policy == eExecutionPolicyAlways) { err.SetErrorString("Expression needed to run in the target, but the target can't be run"); return err; } if (execution_policy == eExecutionPolicyAlways || !can_interpret) { if (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.AsCString()); if (!ir_dynamic_checks.runOnModule(*execution_unit_sp->GetModule())) { err.SetErrorToGenericError(); err.SetErrorString("Couldn't add dynamic checks to the expression"); return err; } } execution_unit_sp->GetRunnableInfo(err, func_addr, func_end); } } else { execution_unit_sp->GetRunnableInfo(err, func_addr, func_end); } return err; }
lldb::ExpressionResults UserExpression::Evaluate (ExecutionContext &exe_ctx, const EvaluateExpressionOptions& options, const char *expr_cstr, const char *expr_prefix, lldb::ValueObjectSP &result_valobj_sp, Error &error, uint32_t line_offset, std::string *fixed_expression, lldb::ModuleSP *jit_module_sp_ptr) { Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy(); lldb::LanguageType language = options.GetLanguage(); const ResultType desired_type = options.DoesCoerceToId() ? UserExpression::eResultTypeId : UserExpression::eResultTypeAny; lldb::ExpressionResults execution_results = lldb::eExpressionSetupError; Target *target = exe_ctx.GetTargetPtr(); if (!target) { if (log) log->Printf("== [UserExpression::Evaluate] Passed a NULL target, can't run expressions."); return lldb::eExpressionSetupError; } Process *process = exe_ctx.GetProcessPtr(); if (process == NULL || process->GetState() != lldb::eStateStopped) { if (execution_policy == eExecutionPolicyAlways) { if (log) log->Printf("== [UserExpression::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; // We need to set the expression execution thread here, turns out parse can call functions in the process of // looking up symbols, which will escape the context set by exe_ctx passed to Execute. lldb::ThreadSP thread_sp = exe_ctx.GetThreadSP(); ThreadList::ExpressionExecutionThreadPusher execution_thread_pusher(thread_sp); const char *full_prefix = NULL; const char *option_prefix = options.GetPrefix(); std::string full_prefix_storage; if (expr_prefix && option_prefix) { full_prefix_storage.assign(expr_prefix); full_prefix_storage.append(option_prefix); if (!full_prefix_storage.empty()) full_prefix = full_prefix_storage.c_str(); } else if (expr_prefix) full_prefix = expr_prefix; else full_prefix = option_prefix; // If the language was not specified in the expression command, // set it to the language in the target's properties if // specified, else default to the langage for the frame. if (language == lldb::eLanguageTypeUnknown) { if (target->GetLanguage() != lldb::eLanguageTypeUnknown) language = target->GetLanguage(); else if (StackFrame *frame = exe_ctx.GetFramePtr()) language = frame->GetLanguage(); } lldb::UserExpressionSP user_expression_sp(target->GetUserExpressionForLanguage (expr_cstr, full_prefix, language, desired_type, options, error)); if (error.Fail()) { if (log) log->Printf ("== [UserExpression::Evaluate] Getting expression: %s ==", error.AsCString()); return lldb::eExpressionSetupError; } if (log) log->Printf("== [UserExpression::Evaluate] Parsing expression %s ==", expr_cstr); const bool keep_expression_in_memory = true; 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; } DiagnosticManager diagnostic_manager; bool parse_success = user_expression_sp->Parse(diagnostic_manager, exe_ctx, execution_policy, keep_expression_in_memory, generate_debug_info); // Calculate the fixed expression always, since we need it for errors. std::string tmp_fixed_expression; if (fixed_expression == nullptr) fixed_expression = &tmp_fixed_expression; const char *fixed_text = user_expression_sp->GetFixedText(); if (fixed_text != nullptr) fixed_expression->append(fixed_text); // If there is a fixed expression, try to parse it: if (!parse_success) { execution_results = lldb::eExpressionParseError; if (fixed_expression && !fixed_expression->empty() && options.GetAutoApplyFixIts()) { lldb::UserExpressionSP fixed_expression_sp(target->GetUserExpressionForLanguage (fixed_expression->c_str(), full_prefix, language, desired_type, options, error)); DiagnosticManager fixed_diagnostic_manager; parse_success = fixed_expression_sp->Parse(fixed_diagnostic_manager, exe_ctx, execution_policy, keep_expression_in_memory, generate_debug_info); if (parse_success) { diagnostic_manager.Clear(); user_expression_sp = fixed_expression_sp; } else { // If the fixed expression failed to parse, don't tell the user about, that won't help. fixed_expression->clear(); } } if (!parse_success) { if (!fixed_expression->empty() && target->GetEnableNotifyAboutFixIts()) { error.SetExpressionErrorWithFormat(execution_results, "expression failed to parse, fixed expression suggested:\n %s", fixed_expression->c_str()); } else { if (!diagnostic_manager.Diagnostics().size()) error.SetExpressionError(execution_results, "expression failed to parse, unknown error"); else error.SetExpressionError(execution_results, diagnostic_manager.GetString().c_str()); } } } if (parse_success) { // If a pointer to a lldb::ModuleSP was passed in, return the JIT'ed module if one was created if (jit_module_sp_ptr) *jit_module_sp_ptr = user_expression_sp->GetJITModule(); lldb::ExpressionVariableSP expr_result; if (execution_policy == eExecutionPolicyNever && !user_expression_sp->CanInterpret()) { if (log) log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant =="); if (!diagnostic_manager.Diagnostics().size()) error.SetExpressionError(lldb::eExpressionSetupError, "expression needed to run but couldn't"); } else if (execution_policy == eExecutionPolicyTopLevel) { error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric); return lldb::eExpressionCompleted; } 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; } diagnostic_manager.Clear(); if (log) log->Printf("== [UserExpression::Evaluate] Executing expression =="); execution_results = user_expression_sp->Execute(diagnostic_manager, exe_ctx, options, user_expression_sp, expr_result); if (execution_results != lldb::eExpressionCompleted) { if (log) log->Printf("== [UserExpression::Evaluate] Execution completed abnormally =="); if (!diagnostic_manager.Diagnostics().size()) error.SetExpressionError(execution_results, "expression failed to execute, unknown error"); else error.SetExpressionError(execution_results, diagnostic_manager.GetString().c_str()); } else { if (expr_result) { result_valobj_sp = expr_result->GetValueObject(); if (log) log->Printf("== [UserExpression::Evaluate] Execution completed normally with result %s ==", result_valobj_sp->GetValueAsCString()); } else { if (log) log->Printf("== [UserExpression::Evaluate] Execution completed normally with no result =="); error.SetError(UserExpression::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); } return execution_results; }