UnwindPlanSP FuncUnwinders::GetUnwindPlanArchitectureDefaultAtFunctionEntry (Thread& thread) { // Lock the mutex to ensure we can always give out the most appropriate // information. We want to make sure if someone requests an unwind // plan, that they get one and don't run into a race condition where one // thread has started to create the unwind plan and has put it into // the auto_ptr member variable, and have another thread enter this function // and return the partially filled pointer contained in the auto_ptr. // We also want to make sure that we lock out other unwind plans from // being accessed until this one is done creating itself in case someone // had some code like: // UnwindPlan *best_unwind_plan = ...GetUnwindPlanAtCallSite (...) // if (best_unwind_plan == NULL) // best_unwind_plan = GetUnwindPlanAtNonCallSite (...) Mutex::Locker locker (m_mutex); if (m_tried_unwind_arch_default_at_func_entry == false && m_unwind_plan_arch_default_at_func_entry_sp.get() == NULL) { m_tried_unwind_arch_default_at_func_entry = true; Address current_pc; ProcessSP process_sp (thread.CalculateProcess()); if (process_sp) { ABI *abi = process_sp->GetABI().get(); if (abi) { m_unwind_plan_arch_default_at_func_entry_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); if (m_unwind_plan_arch_default_at_func_entry_sp) abi->CreateFunctionEntryUnwindPlan(*m_unwind_plan_arch_default_at_func_entry_sp); } } } return m_unwind_plan_arch_default_sp; }
UnwindPlanSP FuncUnwinders::GetUnwindPlanArchitectureDefaultAtFunctionEntry (Thread& thread) { if (m_unwind_plan_arch_default_at_func_entry_sp.get() || m_tried_unwind_arch_default_at_func_entry) return m_unwind_plan_arch_default_at_func_entry_sp; std::lock_guard<std::recursive_mutex> guard(m_mutex); m_tried_unwind_arch_default_at_func_entry = true; Address current_pc; ProcessSP process_sp (thread.CalculateProcess()); if (process_sp) { ABI *abi = process_sp->GetABI().get(); if (abi) { m_unwind_plan_arch_default_at_func_entry_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); if (!abi->CreateFunctionEntryUnwindPlan(*m_unwind_plan_arch_default_at_func_entry_sp)) { m_unwind_plan_arch_default_at_func_entry_sp.reset(); } } } return m_unwind_plan_arch_default_at_func_entry_sp; }
// ThreadPlanCallFunctionUsingABI: Plan to call a single function using the ABI // instead of JIT ThreadPlanCallFunctionUsingABI::ThreadPlanCallFunctionUsingABI( Thread &thread, const Address &function, llvm::Type &prototype, llvm::Type &return_type, llvm::ArrayRef<ABI::CallArgument> args, const EvaluateExpressionOptions &options) : ThreadPlanCallFunction(thread, function, options), m_return_type(return_type) { lldb::addr_t start_load_addr = LLDB_INVALID_ADDRESS; lldb::addr_t function_load_addr = LLDB_INVALID_ADDRESS; ABI *abi = nullptr; if (!ConstructorSetup(thread, abi, start_load_addr, function_load_addr)) return; if (!abi->PrepareTrivialCall(thread, m_function_sp, function_load_addr, start_load_addr, prototype, args)) return; ReportRegisterState("ABI Function call was set up. Register state was:"); m_valid = true; }
ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread, const Address &function, const CompilerType &return_type, llvm::ArrayRef<addr_t> args, const EvaluateExpressionOptions &options) : ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion), m_valid (false), m_stop_other_threads (options.GetStopOthers()), m_unwind_on_error (options.DoesUnwindOnError()), m_ignore_breakpoints (options.DoesIgnoreBreakpoints()), m_debug_execution (options.GetDebug()), m_trap_exceptions (options.GetTrapExceptions()), m_function_addr (function), m_function_sp (0), m_takedown_done (false), m_should_clear_objc_exception_bp(false), m_should_clear_cxx_exception_bp (false), m_stop_address (LLDB_INVALID_ADDRESS), m_expression_language (options.GetLanguage()), m_hit_error_backstop(false), m_return_type (return_type) { lldb::addr_t start_load_addr = LLDB_INVALID_ADDRESS; lldb::addr_t function_load_addr = LLDB_INVALID_ADDRESS; ABI *abi = nullptr; if (!ConstructorSetup (thread, abi, start_load_addr, function_load_addr)) return; if (!abi->PrepareTrivialCall(thread, m_function_sp, function_load_addr, start_load_addr, args)) return; ReportRegisterState ("Function call was set up. Register state was:"); m_valid = true; }