FunctionCaller * UtilityFunction::MakeFunctionCaller (const CompilerType &return_type, const ValueList &arg_value_list, lldb::ThreadSP thread_to_use_sp, Error &error) { if (m_caller_up) return m_caller_up.get(); ProcessSP process_sp = m_jit_process_wp.lock(); if (!process_sp) { error.SetErrorString("Can't make a function caller without a process."); return nullptr; } Address impl_code_address; impl_code_address.SetOffset(StartAddress()); std::string name(m_function_name); name.append("-caller"); m_caller_up.reset (process_sp->GetTarget().GetFunctionCallerForLanguage (Language(), return_type, impl_code_address, arg_value_list, name.c_str(), error)); if (error.Fail()) { return nullptr; } if (m_caller_up) { DiagnosticManager diagnostics; unsigned num_errors = m_caller_up->CompileFunction(thread_to_use_sp, diagnostics); if (num_errors) { error.SetErrorStringWithFormat("Error compiling %s caller function: \"%s\".", m_function_name.c_str(), diagnostics.GetString().c_str()); m_caller_up.reset(); return nullptr; } diagnostics.Clear(); ExecutionContext exe_ctx(process_sp); if (!m_caller_up->WriteFunctionWrapper(exe_ctx, diagnostics)) { error.SetErrorStringWithFormat("Error inserting caller function for %s: \"%s\".", m_function_name.c_str(), diagnostics.GetString().c_str()); m_caller_up.reset(); return nullptr; } } return m_caller_up.get(); }
bool BreakpointLocation::ConditionSaysStop(ExecutionContext &exe_ctx, Status &error) { Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS); std::lock_guard<std::mutex> guard(m_condition_mutex); size_t condition_hash; const char *condition_text = GetConditionText(&condition_hash); if (!condition_text) { m_user_expression_sp.reset(); return false; } error.Clear(); DiagnosticManager diagnostics; if (condition_hash != m_condition_hash || !m_user_expression_sp || !m_user_expression_sp->MatchesContext(exe_ctx)) { LanguageType language = eLanguageTypeUnknown; // See if we can figure out the language from the frame, otherwise use the // default language: CompileUnit *comp_unit = m_address.CalculateSymbolContextCompileUnit(); if (comp_unit) language = comp_unit->GetLanguage(); m_user_expression_sp.reset(GetTarget().GetUserExpressionForLanguage( condition_text, llvm::StringRef(), language, Expression::eResultTypeAny, EvaluateExpressionOptions(), nullptr, error)); if (error.Fail()) { if (log) log->Printf("Error getting condition expression: %s.", error.AsCString()); m_user_expression_sp.reset(); return true; } if (!m_user_expression_sp->Parse(diagnostics, exe_ctx, eExecutionPolicyOnlyWhenNeeded, true, false)) { error.SetErrorStringWithFormat( "Couldn't parse conditional expression:\n%s", diagnostics.GetString().c_str()); m_user_expression_sp.reset(); return true; } m_condition_hash = condition_hash; } // We need to make sure the user sees any parse errors in their condition, so // we'll hook the constructor errors up to the debugger's Async I/O. ValueObjectSP result_value_sp; EvaluateExpressionOptions options; options.SetUnwindOnError(true); options.SetIgnoreBreakpoints(true); options.SetTryAllThreads(true); options.SetResultIsInternal( true); // Don't generate a user variable for condition expressions. Status expr_error; diagnostics.Clear(); ExpressionVariableSP result_variable_sp; ExpressionResults result_code = m_user_expression_sp->Execute( diagnostics, exe_ctx, options, m_user_expression_sp, result_variable_sp); bool ret; if (result_code == eExpressionCompleted) { if (!result_variable_sp) { error.SetErrorString("Expression did not return a result"); return false; } result_value_sp = result_variable_sp->GetValueObject(); if (result_value_sp) { ret = result_value_sp->IsLogicalTrue(error); if (log) { if (error.Success()) { log->Printf("Condition successfully evaluated, result is %s.\n", ret ? "true" : "false"); } else { error.SetErrorString( "Failed to get an integer result from the expression"); ret = false; } } } else { ret = false; error.SetErrorString("Failed to get any result from the expression"); } } else { ret = false; error.SetErrorStringWithFormat("Couldn't execute expression:\n%s", diagnostics.GetString().c_str()); } return ret; }