xref: /freebsd-src/contrib/llvm-project/lldb/source/Expression/FunctionCaller.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
15ffd83dbSDimitry Andric //===-- FunctionCaller.cpp ------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric 
100b57cec5SDimitry Andric #include "lldb/Expression/FunctionCaller.h"
110b57cec5SDimitry Andric #include "lldb/Core/Module.h"
120b57cec5SDimitry Andric #include "lldb/Core/ValueObject.h"
130b57cec5SDimitry Andric #include "lldb/Core/ValueObjectList.h"
140b57cec5SDimitry Andric #include "lldb/Expression/DiagnosticManager.h"
150b57cec5SDimitry Andric #include "lldb/Expression/IRExecutionUnit.h"
160b57cec5SDimitry Andric #include "lldb/Interpreter/CommandReturnObject.h"
170b57cec5SDimitry Andric #include "lldb/Symbol/Function.h"
180b57cec5SDimitry Andric #include "lldb/Symbol/Type.h"
190b57cec5SDimitry Andric #include "lldb/Target/ExecutionContext.h"
200b57cec5SDimitry Andric #include "lldb/Target/Process.h"
210b57cec5SDimitry Andric #include "lldb/Target/RegisterContext.h"
220b57cec5SDimitry Andric #include "lldb/Target/Target.h"
230b57cec5SDimitry Andric #include "lldb/Target/Thread.h"
240b57cec5SDimitry Andric #include "lldb/Target/ThreadPlan.h"
250b57cec5SDimitry Andric #include "lldb/Target/ThreadPlanCallFunction.h"
260b57cec5SDimitry Andric #include "lldb/Utility/DataExtractor.h"
2781ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h"
280b57cec5SDimitry Andric #include "lldb/Utility/Log.h"
290b57cec5SDimitry Andric #include "lldb/Utility/State.h"
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric using namespace lldb_private;
320b57cec5SDimitry Andric 
33480093f4SDimitry Andric char FunctionCaller::ID;
34480093f4SDimitry Andric 
350b57cec5SDimitry Andric // FunctionCaller constructor
360b57cec5SDimitry Andric FunctionCaller::FunctionCaller(ExecutionContextScope &exe_scope,
370b57cec5SDimitry Andric                                const CompilerType &return_type,
380b57cec5SDimitry Andric                                const Address &functionAddress,
390b57cec5SDimitry Andric                                const ValueList &arg_value_list,
400b57cec5SDimitry Andric                                const char *name)
41480093f4SDimitry Andric     : Expression(exe_scope), m_execution_unit_sp(), m_parser(),
42480093f4SDimitry Andric       m_jit_module_wp(), m_name(name ? name : "<unknown>"),
430b57cec5SDimitry Andric       m_function_ptr(nullptr), m_function_addr(functionAddress),
440b57cec5SDimitry Andric       m_function_return_type(return_type),
450b57cec5SDimitry Andric       m_wrapper_function_name("__lldb_caller_function"),
460b57cec5SDimitry Andric       m_wrapper_struct_name("__lldb_caller_struct"), m_wrapper_args_addrs(),
47bdd1243dSDimitry Andric       m_struct_valid(false), m_struct_size(0), m_return_size(0),
48bdd1243dSDimitry Andric       m_return_offset(0), m_arg_values(arg_value_list), m_compiled(false),
490b57cec5SDimitry Andric       m_JITted(false) {
500b57cec5SDimitry Andric   m_jit_process_wp = lldb::ProcessWP(exe_scope.CalculateProcess());
510b57cec5SDimitry Andric   // Can't make a FunctionCaller without a process.
520b57cec5SDimitry Andric   assert(m_jit_process_wp.lock());
530b57cec5SDimitry Andric }
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric // Destructor
560b57cec5SDimitry Andric FunctionCaller::~FunctionCaller() {
570b57cec5SDimitry Andric   lldb::ProcessSP process_sp(m_jit_process_wp.lock());
580b57cec5SDimitry Andric   if (process_sp) {
590b57cec5SDimitry Andric     lldb::ModuleSP jit_module_sp(m_jit_module_wp.lock());
600b57cec5SDimitry Andric     if (jit_module_sp)
610b57cec5SDimitry Andric       process_sp->GetTarget().GetImages().Remove(jit_module_sp);
620b57cec5SDimitry Andric   }
630b57cec5SDimitry Andric }
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric bool FunctionCaller::WriteFunctionWrapper(
660b57cec5SDimitry Andric     ExecutionContext &exe_ctx, DiagnosticManager &diagnostic_manager) {
670b57cec5SDimitry Andric   Process *process = exe_ctx.GetProcessPtr();
680b57cec5SDimitry Andric 
69bdd1243dSDimitry Andric   if (!process) {
70*0fca6ea1SDimitry Andric     diagnostic_manager.Printf(lldb::eSeverityError, "no process.");
710b57cec5SDimitry Andric     return false;
72bdd1243dSDimitry Andric   }
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric   lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock());
750b57cec5SDimitry Andric 
76bdd1243dSDimitry Andric   if (process != jit_process_sp.get()) {
77*0fca6ea1SDimitry Andric     diagnostic_manager.Printf(lldb::eSeverityError,
78bdd1243dSDimitry Andric                               "process does not match the stored process.");
790b57cec5SDimitry Andric     return false;
80bdd1243dSDimitry Andric   }
810b57cec5SDimitry Andric 
82bdd1243dSDimitry Andric   if (process->GetState() != lldb::eStateStopped) {
83*0fca6ea1SDimitry Andric     diagnostic_manager.Printf(lldb::eSeverityError, "process is not stopped");
840b57cec5SDimitry Andric     return false;
85bdd1243dSDimitry Andric   }
86bdd1243dSDimitry Andric 
87bdd1243dSDimitry Andric   if (!m_compiled) {
88*0fca6ea1SDimitry Andric     diagnostic_manager.Printf(lldb::eSeverityError, "function not compiled");
89bdd1243dSDimitry Andric     return false;
90bdd1243dSDimitry Andric   }
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric   if (m_JITted)
930b57cec5SDimitry Andric     return true;
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric   bool can_interpret = false; // should stay that way
960b57cec5SDimitry Andric 
970b57cec5SDimitry Andric   Status jit_error(m_parser->PrepareForExecution(
980b57cec5SDimitry Andric       m_jit_start_addr, m_jit_end_addr, m_execution_unit_sp, exe_ctx,
990b57cec5SDimitry Andric       can_interpret, eExecutionPolicyAlways));
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric   if (!jit_error.Success()) {
102*0fca6ea1SDimitry Andric     diagnostic_manager.Printf(lldb::eSeverityError,
1030b57cec5SDimitry Andric                               "Error in PrepareForExecution: %s.",
1040b57cec5SDimitry Andric                               jit_error.AsCString());
1050b57cec5SDimitry Andric     return false;
1060b57cec5SDimitry Andric   }
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric   if (m_parser->GetGenerateDebugInfo()) {
1090b57cec5SDimitry Andric     lldb::ModuleSP jit_module_sp(m_execution_unit_sp->GetJITModule());
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric     if (jit_module_sp) {
1120b57cec5SDimitry Andric       ConstString const_func_name(FunctionName());
1130b57cec5SDimitry Andric       FileSpec jit_file;
114bdd1243dSDimitry Andric       jit_file.SetFilename(const_func_name);
1150b57cec5SDimitry Andric       jit_module_sp->SetFileSpecAndObjectName(jit_file, ConstString());
1160b57cec5SDimitry Andric       m_jit_module_wp = jit_module_sp;
1170b57cec5SDimitry Andric       process->GetTarget().GetImages().Append(jit_module_sp,
1180b57cec5SDimitry Andric                                               true /* notify */);
1190b57cec5SDimitry Andric     }
1200b57cec5SDimitry Andric   }
1210b57cec5SDimitry Andric   if (process && m_jit_start_addr)
1220b57cec5SDimitry Andric     m_jit_process_wp = process->shared_from_this();
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric   m_JITted = true;
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric   return true;
1270b57cec5SDimitry Andric }
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric bool FunctionCaller::WriteFunctionArguments(
1300b57cec5SDimitry Andric     ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref,
1310b57cec5SDimitry Andric     DiagnosticManager &diagnostic_manager) {
1320b57cec5SDimitry Andric   return WriteFunctionArguments(exe_ctx, args_addr_ref, m_arg_values,
1330b57cec5SDimitry Andric                                 diagnostic_manager);
1340b57cec5SDimitry Andric }
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric // FIXME: Assure that the ValueList we were passed in is consistent with the one
1370b57cec5SDimitry Andric // that defined this function.
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric bool FunctionCaller::WriteFunctionArguments(
1400b57cec5SDimitry Andric     ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref,
1410b57cec5SDimitry Andric     ValueList &arg_values, DiagnosticManager &diagnostic_manager) {
1420b57cec5SDimitry Andric   // All the information to reconstruct the struct is provided by the
1430b57cec5SDimitry Andric   // StructExtractor.
1440b57cec5SDimitry Andric   if (!m_struct_valid) {
145*0fca6ea1SDimitry Andric     diagnostic_manager.PutString(lldb::eSeverityError,
1460b57cec5SDimitry Andric                                  "Argument information was not correctly "
1470b57cec5SDimitry Andric                                  "parsed, so the function cannot be called.");
1480b57cec5SDimitry Andric     return false;
1490b57cec5SDimitry Andric   }
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric   Status error;
1520b57cec5SDimitry Andric   lldb::ExpressionResults return_value = lldb::eExpressionSetupError;
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric   Process *process = exe_ctx.GetProcessPtr();
1550b57cec5SDimitry Andric 
1560b57cec5SDimitry Andric   if (process == nullptr)
1570b57cec5SDimitry Andric     return return_value;
1580b57cec5SDimitry Andric 
1590b57cec5SDimitry Andric   lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock());
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric   if (process != jit_process_sp.get())
1620b57cec5SDimitry Andric     return false;
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric   if (args_addr_ref == LLDB_INVALID_ADDRESS) {
1650b57cec5SDimitry Andric     args_addr_ref = process->AllocateMemory(
1660b57cec5SDimitry Andric         m_struct_size, lldb::ePermissionsReadable | lldb::ePermissionsWritable,
1670b57cec5SDimitry Andric         error);
1680b57cec5SDimitry Andric     if (args_addr_ref == LLDB_INVALID_ADDRESS)
1690b57cec5SDimitry Andric       return false;
1700b57cec5SDimitry Andric     m_wrapper_args_addrs.push_back(args_addr_ref);
1710b57cec5SDimitry Andric   } else {
1720b57cec5SDimitry Andric     // Make sure this is an address that we've already handed out.
1730b57cec5SDimitry Andric     if (find(m_wrapper_args_addrs.begin(), m_wrapper_args_addrs.end(),
1740b57cec5SDimitry Andric              args_addr_ref) == m_wrapper_args_addrs.end()) {
1750b57cec5SDimitry Andric       return false;
1760b57cec5SDimitry Andric     }
1770b57cec5SDimitry Andric   }
1780b57cec5SDimitry Andric 
1790b57cec5SDimitry Andric   // TODO: verify fun_addr needs to be a callable address
1800b57cec5SDimitry Andric   Scalar fun_addr(
1810b57cec5SDimitry Andric       m_function_addr.GetCallableLoadAddress(exe_ctx.GetTargetPtr()));
1820b57cec5SDimitry Andric   uint64_t first_offset = m_member_offsets[0];
1830b57cec5SDimitry Andric   process->WriteScalarToMemory(args_addr_ref + first_offset, fun_addr,
1840b57cec5SDimitry Andric                                process->GetAddressByteSize(), error);
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric   // FIXME: We will need to extend this for Variadic functions.
1870b57cec5SDimitry Andric 
1880b57cec5SDimitry Andric   Status value_error;
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric   size_t num_args = arg_values.GetSize();
1910b57cec5SDimitry Andric   if (num_args != m_arg_values.GetSize()) {
1920b57cec5SDimitry Andric     diagnostic_manager.Printf(
193*0fca6ea1SDimitry Andric         lldb::eSeverityError,
1940b57cec5SDimitry Andric         "Wrong number of arguments - was: %" PRIu64 " should be: %" PRIu64 "",
1950b57cec5SDimitry Andric         (uint64_t)num_args, (uint64_t)m_arg_values.GetSize());
1960b57cec5SDimitry Andric     return false;
1970b57cec5SDimitry Andric   }
1980b57cec5SDimitry Andric 
1990b57cec5SDimitry Andric   for (size_t i = 0; i < num_args; i++) {
2000b57cec5SDimitry Andric     // FIXME: We should sanity check sizes.
2010b57cec5SDimitry Andric 
2020b57cec5SDimitry Andric     uint64_t offset = m_member_offsets[i + 1]; // Clang sizes are in bytes.
2030b57cec5SDimitry Andric     Value *arg_value = arg_values.GetValueAtIndex(i);
2040b57cec5SDimitry Andric 
2050b57cec5SDimitry Andric     // FIXME: For now just do scalars:
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric     // Special case: if it's a pointer, don't do anything (the ABI supports
2080b57cec5SDimitry Andric     // passing cstrings)
2090b57cec5SDimitry Andric 
210fe6060f1SDimitry Andric     if (arg_value->GetValueType() == Value::ValueType::HostAddress &&
211fe6060f1SDimitry Andric         arg_value->GetContextType() == Value::ContextType::Invalid &&
2120b57cec5SDimitry Andric         arg_value->GetCompilerType().IsPointerType())
2130b57cec5SDimitry Andric       continue;
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric     const Scalar &arg_scalar = arg_value->ResolveValue(&exe_ctx);
2160b57cec5SDimitry Andric 
2170b57cec5SDimitry Andric     if (!process->WriteScalarToMemory(args_addr_ref + offset, arg_scalar,
2180b57cec5SDimitry Andric                                       arg_scalar.GetByteSize(), error))
2190b57cec5SDimitry Andric       return false;
2200b57cec5SDimitry Andric   }
2210b57cec5SDimitry Andric 
2220b57cec5SDimitry Andric   return true;
2230b57cec5SDimitry Andric }
2240b57cec5SDimitry Andric 
2250b57cec5SDimitry Andric bool FunctionCaller::InsertFunction(ExecutionContext &exe_ctx,
2260b57cec5SDimitry Andric                                     lldb::addr_t &args_addr_ref,
2270b57cec5SDimitry Andric                                     DiagnosticManager &diagnostic_manager) {
228bdd1243dSDimitry Andric   // Since we might need to call allocate memory and maybe call code to make
229bdd1243dSDimitry Andric   // the caller, we need to be stopped.
230bdd1243dSDimitry Andric   Process *process = exe_ctx.GetProcessPtr();
231bdd1243dSDimitry Andric   if (!process) {
232*0fca6ea1SDimitry Andric     diagnostic_manager.PutString(lldb::eSeverityError, "no process");
233bdd1243dSDimitry Andric     return false;
234bdd1243dSDimitry Andric   }
235bdd1243dSDimitry Andric   if (process->GetState() != lldb::eStateStopped) {
236*0fca6ea1SDimitry Andric     diagnostic_manager.PutString(lldb::eSeverityError, "process running");
237bdd1243dSDimitry Andric     return false;
238bdd1243dSDimitry Andric   }
2390b57cec5SDimitry Andric   if (CompileFunction(exe_ctx.GetThreadSP(), diagnostic_manager) != 0)
2400b57cec5SDimitry Andric     return false;
2410b57cec5SDimitry Andric   if (!WriteFunctionWrapper(exe_ctx, diagnostic_manager))
2420b57cec5SDimitry Andric     return false;
2430b57cec5SDimitry Andric   if (!WriteFunctionArguments(exe_ctx, args_addr_ref, diagnostic_manager))
2440b57cec5SDimitry Andric     return false;
2450b57cec5SDimitry Andric 
24681ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Step);
2479dba64beSDimitry Andric   LLDB_LOGF(log, "Call Address: 0x%" PRIx64 " Struct Address: 0x%" PRIx64 ".\n",
2480b57cec5SDimitry Andric             m_jit_start_addr, args_addr_ref);
2490b57cec5SDimitry Andric 
2500b57cec5SDimitry Andric   return true;
2510b57cec5SDimitry Andric }
2520b57cec5SDimitry Andric 
2530b57cec5SDimitry Andric lldb::ThreadPlanSP FunctionCaller::GetThreadPlanToCallFunction(
2540b57cec5SDimitry Andric     ExecutionContext &exe_ctx, lldb::addr_t args_addr,
2550b57cec5SDimitry Andric     const EvaluateExpressionOptions &options,
2560b57cec5SDimitry Andric     DiagnosticManager &diagnostic_manager) {
25781ad6265SDimitry Andric   Log *log(GetLog(LLDBLog::Expressions | LLDBLog::Step));
2580b57cec5SDimitry Andric 
2599dba64beSDimitry Andric   LLDB_LOGF(log,
2609dba64beSDimitry Andric             "-- [FunctionCaller::GetThreadPlanToCallFunction] Creating "
2610b57cec5SDimitry Andric             "thread plan to call function \"%s\" --",
2620b57cec5SDimitry Andric             m_name.c_str());
2630b57cec5SDimitry Andric 
2640b57cec5SDimitry Andric   // FIXME: Use the errors Stream for better error reporting.
2650b57cec5SDimitry Andric   Thread *thread = exe_ctx.GetThreadPtr();
2660b57cec5SDimitry Andric   if (thread == nullptr) {
2670b57cec5SDimitry Andric     diagnostic_manager.PutString(
268*0fca6ea1SDimitry Andric         lldb::eSeverityError, "Can't call a function without a valid thread.");
2690b57cec5SDimitry Andric     return nullptr;
2700b57cec5SDimitry Andric   }
2710b57cec5SDimitry Andric 
2720b57cec5SDimitry Andric   // Okay, now run the function:
2730b57cec5SDimitry Andric 
2740b57cec5SDimitry Andric   Address wrapper_address(m_jit_start_addr);
2750b57cec5SDimitry Andric 
2760b57cec5SDimitry Andric   lldb::addr_t args = {args_addr};
2770b57cec5SDimitry Andric 
2780b57cec5SDimitry Andric   lldb::ThreadPlanSP new_plan_sp(new ThreadPlanCallFunction(
2790b57cec5SDimitry Andric       *thread, wrapper_address, CompilerType(), args, options));
280349cc55cSDimitry Andric   new_plan_sp->SetIsControllingPlan(true);
2810b57cec5SDimitry Andric   new_plan_sp->SetOkayToDiscard(false);
2820b57cec5SDimitry Andric   return new_plan_sp;
2830b57cec5SDimitry Andric }
2840b57cec5SDimitry Andric 
2850b57cec5SDimitry Andric bool FunctionCaller::FetchFunctionResults(ExecutionContext &exe_ctx,
2860b57cec5SDimitry Andric                                           lldb::addr_t args_addr,
2870b57cec5SDimitry Andric                                           Value &ret_value) {
2880b57cec5SDimitry Andric   // Read the return value - it is the last field in the struct:
2890b57cec5SDimitry Andric   // FIXME: How does clang tell us there's no return value?  We need to handle
2900b57cec5SDimitry Andric   // that case.
2910b57cec5SDimitry Andric   // FIXME: Create our ThreadPlanCallFunction with the return CompilerType, and
2920b57cec5SDimitry Andric   // then use GetReturnValueObject
2930b57cec5SDimitry Andric   // to fetch the value.  That way we can fetch any values we need.
2940b57cec5SDimitry Andric 
29581ad6265SDimitry Andric   Log *log(GetLog(LLDBLog::Expressions | LLDBLog::Step));
2960b57cec5SDimitry Andric 
2979dba64beSDimitry Andric   LLDB_LOGF(log,
2989dba64beSDimitry Andric             "-- [FunctionCaller::FetchFunctionResults] Fetching function "
2990b57cec5SDimitry Andric             "results for \"%s\"--",
3000b57cec5SDimitry Andric             m_name.c_str());
3010b57cec5SDimitry Andric 
3020b57cec5SDimitry Andric   Process *process = exe_ctx.GetProcessPtr();
3030b57cec5SDimitry Andric 
3040b57cec5SDimitry Andric   if (process == nullptr)
3050b57cec5SDimitry Andric     return false;
3060b57cec5SDimitry Andric 
3070b57cec5SDimitry Andric   lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock());
3080b57cec5SDimitry Andric 
3090b57cec5SDimitry Andric   if (process != jit_process_sp.get())
3100b57cec5SDimitry Andric     return false;
3110b57cec5SDimitry Andric 
3120b57cec5SDimitry Andric   Status error;
3130b57cec5SDimitry Andric   ret_value.GetScalar() = process->ReadUnsignedIntegerFromMemory(
3140b57cec5SDimitry Andric       args_addr + m_return_offset, m_return_size, 0, error);
3150b57cec5SDimitry Andric 
3160b57cec5SDimitry Andric   if (error.Fail())
3170b57cec5SDimitry Andric     return false;
3180b57cec5SDimitry Andric 
3190b57cec5SDimitry Andric   ret_value.SetCompilerType(m_function_return_type);
320fe6060f1SDimitry Andric   ret_value.SetValueType(Value::ValueType::Scalar);
3210b57cec5SDimitry Andric   return true;
3220b57cec5SDimitry Andric }
3230b57cec5SDimitry Andric 
3240b57cec5SDimitry Andric void FunctionCaller::DeallocateFunctionResults(ExecutionContext &exe_ctx,
3250b57cec5SDimitry Andric                                                lldb::addr_t args_addr) {
3260b57cec5SDimitry Andric   std::list<lldb::addr_t>::iterator pos;
3270b57cec5SDimitry Andric   pos = std::find(m_wrapper_args_addrs.begin(), m_wrapper_args_addrs.end(),
3280b57cec5SDimitry Andric                   args_addr);
3290b57cec5SDimitry Andric   if (pos != m_wrapper_args_addrs.end())
3300b57cec5SDimitry Andric     m_wrapper_args_addrs.erase(pos);
3310b57cec5SDimitry Andric 
3320b57cec5SDimitry Andric   exe_ctx.GetProcessRef().DeallocateMemory(args_addr);
3330b57cec5SDimitry Andric }
3340b57cec5SDimitry Andric 
3350b57cec5SDimitry Andric lldb::ExpressionResults FunctionCaller::ExecuteFunction(
3360b57cec5SDimitry Andric     ExecutionContext &exe_ctx, lldb::addr_t *args_addr_ptr,
3370b57cec5SDimitry Andric     const EvaluateExpressionOptions &options,
3380b57cec5SDimitry Andric     DiagnosticManager &diagnostic_manager, Value &results) {
3390b57cec5SDimitry Andric   lldb::ExpressionResults return_value = lldb::eExpressionSetupError;
3400b57cec5SDimitry Andric 
3410b57cec5SDimitry Andric   // FunctionCaller::ExecuteFunction execution is always just to get the
342fe6060f1SDimitry Andric   // result. Unless explicitly asked for, ignore breakpoints and unwind on
343fe6060f1SDimitry Andric   // error.
344fe6060f1SDimitry Andric   const bool enable_debugging =
345fe6060f1SDimitry Andric       exe_ctx.GetTargetPtr() &&
346fe6060f1SDimitry Andric       exe_ctx.GetTargetPtr()->GetDebugUtilityExpression();
3470b57cec5SDimitry Andric   EvaluateExpressionOptions real_options = options;
348fe6060f1SDimitry Andric   real_options.SetDebug(false); // This halts the expression for debugging.
349fe6060f1SDimitry Andric   real_options.SetGenerateDebugInfo(enable_debugging);
350fe6060f1SDimitry Andric   real_options.SetUnwindOnError(!enable_debugging);
351fe6060f1SDimitry Andric   real_options.SetIgnoreBreakpoints(!enable_debugging);
3520b57cec5SDimitry Andric 
3530b57cec5SDimitry Andric   lldb::addr_t args_addr;
3540b57cec5SDimitry Andric 
3550b57cec5SDimitry Andric   if (args_addr_ptr != nullptr)
3560b57cec5SDimitry Andric     args_addr = *args_addr_ptr;
3570b57cec5SDimitry Andric   else
3580b57cec5SDimitry Andric     args_addr = LLDB_INVALID_ADDRESS;
3590b57cec5SDimitry Andric 
3600b57cec5SDimitry Andric   if (CompileFunction(exe_ctx.GetThreadSP(), diagnostic_manager) != 0)
3610b57cec5SDimitry Andric     return lldb::eExpressionSetupError;
3620b57cec5SDimitry Andric 
3630b57cec5SDimitry Andric   if (args_addr == LLDB_INVALID_ADDRESS) {
3640b57cec5SDimitry Andric     if (!InsertFunction(exe_ctx, args_addr, diagnostic_manager))
3650b57cec5SDimitry Andric       return lldb::eExpressionSetupError;
3660b57cec5SDimitry Andric   }
3670b57cec5SDimitry Andric 
36881ad6265SDimitry Andric   Log *log(GetLog(LLDBLog::Expressions | LLDBLog::Step));
3690b57cec5SDimitry Andric 
3709dba64beSDimitry Andric   LLDB_LOGF(log,
3710b57cec5SDimitry Andric             "== [FunctionCaller::ExecuteFunction] Executing function \"%s\" ==",
3720b57cec5SDimitry Andric             m_name.c_str());
3730b57cec5SDimitry Andric 
3740b57cec5SDimitry Andric   lldb::ThreadPlanSP call_plan_sp = GetThreadPlanToCallFunction(
3750b57cec5SDimitry Andric       exe_ctx, args_addr, real_options, diagnostic_manager);
3760b57cec5SDimitry Andric   if (!call_plan_sp)
3770b57cec5SDimitry Andric     return lldb::eExpressionSetupError;
3780b57cec5SDimitry Andric 
3790b57cec5SDimitry Andric   // We need to make sure we record the fact that we are running an expression
3800b57cec5SDimitry Andric   // here otherwise this fact will fail to be recorded when fetching an
3810b57cec5SDimitry Andric   // Objective-C object description
3820b57cec5SDimitry Andric   if (exe_ctx.GetProcessPtr())
3830b57cec5SDimitry Andric     exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
3840b57cec5SDimitry Andric 
3850b57cec5SDimitry Andric   return_value = exe_ctx.GetProcessRef().RunThreadPlan(
3860b57cec5SDimitry Andric       exe_ctx, call_plan_sp, real_options, diagnostic_manager);
3870b57cec5SDimitry Andric 
3880b57cec5SDimitry Andric   if (log) {
3890b57cec5SDimitry Andric     if (return_value != lldb::eExpressionCompleted) {
3909dba64beSDimitry Andric       LLDB_LOGF(log,
3919dba64beSDimitry Andric                 "== [FunctionCaller::ExecuteFunction] Execution of \"%s\" "
3925ffd83dbSDimitry Andric                 "completed abnormally: %s ==",
3935ffd83dbSDimitry Andric                 m_name.c_str(),
3945ffd83dbSDimitry Andric                 Process::ExecutionResultAsCString(return_value));
3950b57cec5SDimitry Andric     } else {
3969dba64beSDimitry Andric       LLDB_LOGF(log,
3979dba64beSDimitry Andric                 "== [FunctionCaller::ExecuteFunction] Execution of \"%s\" "
3980b57cec5SDimitry Andric                 "completed normally ==",
3990b57cec5SDimitry Andric                 m_name.c_str());
4000b57cec5SDimitry Andric     }
4010b57cec5SDimitry Andric   }
4020b57cec5SDimitry Andric 
4030b57cec5SDimitry Andric   if (exe_ctx.GetProcessPtr())
4040b57cec5SDimitry Andric     exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
4050b57cec5SDimitry Andric 
4060b57cec5SDimitry Andric   if (args_addr_ptr != nullptr)
4070b57cec5SDimitry Andric     *args_addr_ptr = args_addr;
4080b57cec5SDimitry Andric 
4090b57cec5SDimitry Andric   if (return_value != lldb::eExpressionCompleted)
4100b57cec5SDimitry Andric     return return_value;
4110b57cec5SDimitry Andric 
4120b57cec5SDimitry Andric   FetchFunctionResults(exe_ctx, args_addr, results);
4130b57cec5SDimitry Andric 
4140b57cec5SDimitry Andric   if (args_addr_ptr == nullptr)
4150b57cec5SDimitry Andric     DeallocateFunctionResults(exe_ctx, args_addr);
4160b57cec5SDimitry Andric 
4170b57cec5SDimitry Andric   return lldb::eExpressionCompleted;
4180b57cec5SDimitry Andric }
419