15ffd83dbSDimitry Andric //===-- ThreadPlanCallFunction.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 #include "lldb/Target/ThreadPlanCallFunction.h" 100b57cec5SDimitry Andric #include "lldb/Breakpoint/Breakpoint.h" 110b57cec5SDimitry Andric #include "lldb/Breakpoint/BreakpointLocation.h" 120b57cec5SDimitry Andric #include "lldb/Core/Address.h" 130b57cec5SDimitry Andric #include "lldb/Core/DumpRegisterValue.h" 140b57cec5SDimitry Andric #include "lldb/Core/Module.h" 150b57cec5SDimitry Andric #include "lldb/Symbol/ObjectFile.h" 160b57cec5SDimitry Andric #include "lldb/Target/ABI.h" 170b57cec5SDimitry Andric #include "lldb/Target/LanguageRuntime.h" 180b57cec5SDimitry Andric #include "lldb/Target/Process.h" 190b57cec5SDimitry Andric #include "lldb/Target/RegisterContext.h" 200b57cec5SDimitry Andric #include "lldb/Target/StopInfo.h" 210b57cec5SDimitry Andric #include "lldb/Target/Target.h" 220b57cec5SDimitry Andric #include "lldb/Target/Thread.h" 230b57cec5SDimitry Andric #include "lldb/Target/ThreadPlanRunToAddress.h" 2481ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h" 250b57cec5SDimitry Andric #include "lldb/Utility/Log.h" 260b57cec5SDimitry Andric #include "lldb/Utility/Stream.h" 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric #include <memory> 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric using namespace lldb; 310b57cec5SDimitry Andric using namespace lldb_private; 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric // ThreadPlanCallFunction: Plan to call a single function 340b57cec5SDimitry Andric bool ThreadPlanCallFunction::ConstructorSetup( 350b57cec5SDimitry Andric Thread &thread, ABI *&abi, lldb::addr_t &start_load_addr, 360b57cec5SDimitry Andric lldb::addr_t &function_load_addr) { 37349cc55cSDimitry Andric SetIsControllingPlan(true); 380b57cec5SDimitry Andric SetOkayToDiscard(false); 390b57cec5SDimitry Andric SetPrivate(true); 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric ProcessSP process_sp(thread.GetProcess()); 420b57cec5SDimitry Andric if (!process_sp) 430b57cec5SDimitry Andric return false; 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric abi = process_sp->GetABI().get(); 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric if (!abi) 480b57cec5SDimitry Andric return false; 490b57cec5SDimitry Andric 5081ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Step); 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric SetBreakpoints(); 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric m_function_sp = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize(); 550b57cec5SDimitry Andric // If we can't read memory at the point of the process where we are planning 560b57cec5SDimitry Andric // to put our function, we're not going to get any further... 570b57cec5SDimitry Andric Status error; 580b57cec5SDimitry Andric process_sp->ReadUnsignedIntegerFromMemory(m_function_sp, 4, 0, error); 590b57cec5SDimitry Andric if (!error.Success()) { 600b57cec5SDimitry Andric m_constructor_errors.Printf( 610b57cec5SDimitry Andric "Trying to put the stack in unreadable memory at: 0x%" PRIx64 ".", 620b57cec5SDimitry Andric m_function_sp); 639dba64beSDimitry Andric LLDB_LOGF(log, "ThreadPlanCallFunction(%p): %s.", static_cast<void *>(this), 640b57cec5SDimitry Andric m_constructor_errors.GetData()); 650b57cec5SDimitry Andric return false; 660b57cec5SDimitry Andric } 670b57cec5SDimitry Andric 689dba64beSDimitry Andric llvm::Expected<Address> start_address = GetTarget().GetEntryPointAddress(); 699dba64beSDimitry Andric if (!start_address) { 700b57cec5SDimitry Andric m_constructor_errors.Printf( 719dba64beSDimitry Andric "%s", llvm::toString(start_address.takeError()).c_str()); 729dba64beSDimitry Andric LLDB_LOGF(log, "ThreadPlanCallFunction(%p): %s.", static_cast<void *>(this), 730b57cec5SDimitry Andric m_constructor_errors.GetData()); 740b57cec5SDimitry Andric return false; 750b57cec5SDimitry Andric } 760b57cec5SDimitry Andric 779dba64beSDimitry Andric m_start_addr = *start_address; 780b57cec5SDimitry Andric start_load_addr = m_start_addr.GetLoadAddress(&GetTarget()); 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric // Checkpoint the thread state so we can restore it later. 810b57cec5SDimitry Andric if (log && log->GetVerbose()) 820b57cec5SDimitry Andric ReportRegisterState("About to checkpoint thread before function call. " 830b57cec5SDimitry Andric "Original register state was:"); 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric if (!thread.CheckpointThreadState(m_stored_thread_state)) { 860b57cec5SDimitry Andric m_constructor_errors.Printf("Setting up ThreadPlanCallFunction, failed to " 870b57cec5SDimitry Andric "checkpoint thread state."); 889dba64beSDimitry Andric LLDB_LOGF(log, "ThreadPlanCallFunction(%p): %s.", static_cast<void *>(this), 890b57cec5SDimitry Andric m_constructor_errors.GetData()); 900b57cec5SDimitry Andric return false; 910b57cec5SDimitry Andric } 920b57cec5SDimitry Andric function_load_addr = m_function_addr.GetLoadAddress(&GetTarget()); 930b57cec5SDimitry Andric 940b57cec5SDimitry Andric return true; 950b57cec5SDimitry Andric } 960b57cec5SDimitry Andric 970b57cec5SDimitry Andric ThreadPlanCallFunction::ThreadPlanCallFunction( 980b57cec5SDimitry Andric Thread &thread, const Address &function, const CompilerType &return_type, 990b57cec5SDimitry Andric llvm::ArrayRef<addr_t> args, const EvaluateExpressionOptions &options) 1000b57cec5SDimitry Andric : ThreadPlan(ThreadPlan::eKindCallFunction, "Call function plan", thread, 1010b57cec5SDimitry Andric eVoteNoOpinion, eVoteNoOpinion), 1020b57cec5SDimitry Andric m_valid(false), m_stop_other_threads(options.GetStopOthers()), 1030b57cec5SDimitry Andric m_unwind_on_error(options.DoesUnwindOnError()), 1040b57cec5SDimitry Andric m_ignore_breakpoints(options.DoesIgnoreBreakpoints()), 1050b57cec5SDimitry Andric m_debug_execution(options.GetDebug()), 1060b57cec5SDimitry Andric m_trap_exceptions(options.GetTrapExceptions()), m_function_addr(function), 107972a253aSDimitry Andric m_start_addr(), m_function_sp(0), m_subplan_sp(), 108972a253aSDimitry Andric m_cxx_language_runtime(nullptr), m_objc_language_runtime(nullptr), 109972a253aSDimitry Andric m_stored_thread_state(), m_real_stop_info_sp(), m_constructor_errors(), 110972a253aSDimitry Andric m_return_valobj_sp(), m_takedown_done(false), 1110b57cec5SDimitry Andric m_should_clear_objc_exception_bp(false), 1120b57cec5SDimitry Andric m_should_clear_cxx_exception_bp(false), 1130b57cec5SDimitry Andric m_stop_address(LLDB_INVALID_ADDRESS), m_return_type(return_type) { 1140b57cec5SDimitry Andric lldb::addr_t start_load_addr = LLDB_INVALID_ADDRESS; 1150b57cec5SDimitry Andric lldb::addr_t function_load_addr = LLDB_INVALID_ADDRESS; 1160b57cec5SDimitry Andric ABI *abi = nullptr; 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric if (!ConstructorSetup(thread, abi, start_load_addr, function_load_addr)) 1190b57cec5SDimitry Andric return; 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric if (!abi->PrepareTrivialCall(thread, m_function_sp, function_load_addr, 1220b57cec5SDimitry Andric start_load_addr, args)) 1230b57cec5SDimitry Andric return; 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric ReportRegisterState("Function call was set up. Register state was:"); 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric m_valid = true; 1280b57cec5SDimitry Andric } 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric ThreadPlanCallFunction::ThreadPlanCallFunction( 1310b57cec5SDimitry Andric Thread &thread, const Address &function, 1320b57cec5SDimitry Andric const EvaluateExpressionOptions &options) 1330b57cec5SDimitry Andric : ThreadPlan(ThreadPlan::eKindCallFunction, "Call function plan", thread, 1340b57cec5SDimitry Andric eVoteNoOpinion, eVoteNoOpinion), 1350b57cec5SDimitry Andric m_valid(false), m_stop_other_threads(options.GetStopOthers()), 1360b57cec5SDimitry Andric m_unwind_on_error(options.DoesUnwindOnError()), 1370b57cec5SDimitry Andric m_ignore_breakpoints(options.DoesIgnoreBreakpoints()), 1380b57cec5SDimitry Andric m_debug_execution(options.GetDebug()), 1390b57cec5SDimitry Andric m_trap_exceptions(options.GetTrapExceptions()), m_function_addr(function), 140972a253aSDimitry Andric m_start_addr(), m_function_sp(0), m_subplan_sp(), 141972a253aSDimitry Andric m_cxx_language_runtime(nullptr), m_objc_language_runtime(nullptr), 142972a253aSDimitry Andric m_stored_thread_state(), m_real_stop_info_sp(), m_constructor_errors(), 143972a253aSDimitry Andric m_return_valobj_sp(), m_takedown_done(false), 1440b57cec5SDimitry Andric m_should_clear_objc_exception_bp(false), 1450b57cec5SDimitry Andric m_should_clear_cxx_exception_bp(false), 1460b57cec5SDimitry Andric m_stop_address(LLDB_INVALID_ADDRESS), m_return_type(CompilerType()) {} 1470b57cec5SDimitry Andric 1480b57cec5SDimitry Andric ThreadPlanCallFunction::~ThreadPlanCallFunction() { 1490b57cec5SDimitry Andric DoTakedown(PlanSucceeded()); 1500b57cec5SDimitry Andric } 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric void ThreadPlanCallFunction::ReportRegisterState(const char *message) { 15381ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Step); 1540b57cec5SDimitry Andric if (log && log->GetVerbose()) { 1550b57cec5SDimitry Andric StreamString strm; 1565ffd83dbSDimitry Andric RegisterContext *reg_ctx = GetThread().GetRegisterContext().get(); 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric log->PutCString(message); 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric RegisterValue reg_value; 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric for (uint32_t reg_idx = 0, num_registers = reg_ctx->GetRegisterCount(); 1630b57cec5SDimitry Andric reg_idx < num_registers; ++reg_idx) { 1640b57cec5SDimitry Andric const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_idx); 1650b57cec5SDimitry Andric if (reg_ctx->ReadRegister(reg_info, reg_value)) { 166*fe013be4SDimitry Andric DumpRegisterValue(reg_value, strm, *reg_info, true, false, 1670b57cec5SDimitry Andric eFormatDefault); 1680b57cec5SDimitry Andric strm.EOL(); 1690b57cec5SDimitry Andric } 1700b57cec5SDimitry Andric } 1710b57cec5SDimitry Andric log->PutString(strm.GetString()); 1720b57cec5SDimitry Andric } 1730b57cec5SDimitry Andric } 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric void ThreadPlanCallFunction::DoTakedown(bool success) { 17681ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Step); 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric if (!m_valid) { 1790b57cec5SDimitry Andric // Don't call DoTakedown if we were never valid to begin with. 1809dba64beSDimitry Andric LLDB_LOGF(log, 1819dba64beSDimitry Andric "ThreadPlanCallFunction(%p): Log called on " 1820b57cec5SDimitry Andric "ThreadPlanCallFunction that was never valid.", 1830b57cec5SDimitry Andric static_cast<void *>(this)); 1840b57cec5SDimitry Andric return; 1850b57cec5SDimitry Andric } 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric if (!m_takedown_done) { 1885ffd83dbSDimitry Andric Thread &thread = GetThread(); 1890b57cec5SDimitry Andric if (success) { 1900b57cec5SDimitry Andric SetReturnValue(); 1910b57cec5SDimitry Andric } 1929dba64beSDimitry Andric LLDB_LOGF(log, 1939dba64beSDimitry Andric "ThreadPlanCallFunction(%p): DoTakedown called for thread " 1940b57cec5SDimitry Andric "0x%4.4" PRIx64 ", m_valid: %d complete: %d.\n", 1955ffd83dbSDimitry Andric static_cast<void *>(this), m_tid, m_valid, IsPlanComplete()); 1960b57cec5SDimitry Andric m_takedown_done = true; 1970b57cec5SDimitry Andric m_stop_address = 1985ffd83dbSDimitry Andric thread.GetStackFrameAtIndex(0)->GetRegisterContext()->GetPC(); 1990b57cec5SDimitry Andric m_real_stop_info_sp = GetPrivateStopInfo(); 2005ffd83dbSDimitry Andric if (!thread.RestoreRegisterStateFromCheckpoint(m_stored_thread_state)) { 2019dba64beSDimitry Andric LLDB_LOGF(log, 2029dba64beSDimitry Andric "ThreadPlanCallFunction(%p): DoTakedown failed to restore " 2030b57cec5SDimitry Andric "register state", 2040b57cec5SDimitry Andric static_cast<void *>(this)); 2050b57cec5SDimitry Andric } 2060b57cec5SDimitry Andric SetPlanComplete(success); 2070b57cec5SDimitry Andric ClearBreakpoints(); 2080b57cec5SDimitry Andric if (log && log->GetVerbose()) 2090b57cec5SDimitry Andric ReportRegisterState("Restoring thread state after function call. " 2100b57cec5SDimitry Andric "Restored register state:"); 2110b57cec5SDimitry Andric } else { 2129dba64beSDimitry Andric LLDB_LOGF(log, 2139dba64beSDimitry Andric "ThreadPlanCallFunction(%p): DoTakedown called as no-op for " 2140b57cec5SDimitry Andric "thread 0x%4.4" PRIx64 ", m_valid: %d complete: %d.\n", 2155ffd83dbSDimitry Andric static_cast<void *>(this), m_tid, m_valid, IsPlanComplete()); 2160b57cec5SDimitry Andric } 2170b57cec5SDimitry Andric } 2180b57cec5SDimitry Andric 219349cc55cSDimitry Andric void ThreadPlanCallFunction::DidPop() { DoTakedown(PlanSucceeded()); } 2200b57cec5SDimitry Andric 2210b57cec5SDimitry Andric void ThreadPlanCallFunction::GetDescription(Stream *s, DescriptionLevel level) { 2220b57cec5SDimitry Andric if (level == eDescriptionLevelBrief) { 2230b57cec5SDimitry Andric s->Printf("Function call thread plan"); 2240b57cec5SDimitry Andric } else { 2250b57cec5SDimitry Andric s->Printf("Thread plan to call 0x%" PRIx64, 2265ffd83dbSDimitry Andric m_function_addr.GetLoadAddress(&GetTarget())); 2270b57cec5SDimitry Andric } 2280b57cec5SDimitry Andric } 2290b57cec5SDimitry Andric 2300b57cec5SDimitry Andric bool ThreadPlanCallFunction::ValidatePlan(Stream *error) { 2310b57cec5SDimitry Andric if (!m_valid) { 2320b57cec5SDimitry Andric if (error) { 2330b57cec5SDimitry Andric if (m_constructor_errors.GetSize() > 0) 2340b57cec5SDimitry Andric error->PutCString(m_constructor_errors.GetString()); 2350b57cec5SDimitry Andric else 2360b57cec5SDimitry Andric error->PutCString("Unknown error"); 2370b57cec5SDimitry Andric } 2380b57cec5SDimitry Andric return false; 2390b57cec5SDimitry Andric } 2400b57cec5SDimitry Andric 2410b57cec5SDimitry Andric return true; 2420b57cec5SDimitry Andric } 2430b57cec5SDimitry Andric 2440b57cec5SDimitry Andric Vote ThreadPlanCallFunction::ShouldReportStop(Event *event_ptr) { 2450b57cec5SDimitry Andric if (m_takedown_done || IsPlanComplete()) 2460b57cec5SDimitry Andric return eVoteYes; 2470b57cec5SDimitry Andric else 2480b57cec5SDimitry Andric return ThreadPlan::ShouldReportStop(event_ptr); 2490b57cec5SDimitry Andric } 2500b57cec5SDimitry Andric 2510b57cec5SDimitry Andric bool ThreadPlanCallFunction::DoPlanExplainsStop(Event *event_ptr) { 25281ad6265SDimitry Andric Log *log(GetLog(LLDBLog::Step | LLDBLog::Process)); 2530b57cec5SDimitry Andric m_real_stop_info_sp = GetPrivateStopInfo(); 2540b57cec5SDimitry Andric 2550b57cec5SDimitry Andric // If our subplan knows why we stopped, even if it's done (which would 2560b57cec5SDimitry Andric // forward the question to us) we answer yes. 2570b57cec5SDimitry Andric if (m_subplan_sp && m_subplan_sp->PlanExplainsStop(event_ptr)) { 2580b57cec5SDimitry Andric SetPlanComplete(); 2590b57cec5SDimitry Andric return true; 2600b57cec5SDimitry Andric } 2610b57cec5SDimitry Andric 2620b57cec5SDimitry Andric // Check if the breakpoint is one of ours. 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric StopReason stop_reason; 2650b57cec5SDimitry Andric if (!m_real_stop_info_sp) 2660b57cec5SDimitry Andric stop_reason = eStopReasonNone; 2670b57cec5SDimitry Andric else 2680b57cec5SDimitry Andric stop_reason = m_real_stop_info_sp->GetStopReason(); 269e8d8bef9SDimitry Andric LLDB_LOG(log, 270e8d8bef9SDimitry Andric "ThreadPlanCallFunction::PlanExplainsStop: Got stop reason - {0}.", 271e8d8bef9SDimitry Andric Thread::StopReasonAsString(stop_reason)); 2720b57cec5SDimitry Andric 2730b57cec5SDimitry Andric if (stop_reason == eStopReasonBreakpoint && BreakpointsExplainStop()) 2740b57cec5SDimitry Andric return true; 2750b57cec5SDimitry Andric 2760b57cec5SDimitry Andric // One more quirk here. If this event was from Halt interrupting the target, 2770b57cec5SDimitry Andric // then we should not consider ourselves complete. Return true to 2780b57cec5SDimitry Andric // acknowledge the stop. 2790b57cec5SDimitry Andric if (Process::ProcessEventData::GetInterruptedFromEvent(event_ptr)) { 2809dba64beSDimitry Andric LLDB_LOGF(log, "ThreadPlanCallFunction::PlanExplainsStop: The event is an " 2810b57cec5SDimitry Andric "Interrupt, returning true."); 2820b57cec5SDimitry Andric return true; 2830b57cec5SDimitry Andric } 2840b57cec5SDimitry Andric // We control breakpoints separately from other "stop reasons." So first, 2850b57cec5SDimitry Andric // check the case where we stopped for an internal breakpoint, in that case, 2860b57cec5SDimitry Andric // continue on. If it is not an internal breakpoint, consult 2870b57cec5SDimitry Andric // m_ignore_breakpoints. 2880b57cec5SDimitry Andric 2890b57cec5SDimitry Andric if (stop_reason == eStopReasonBreakpoint) { 2900b57cec5SDimitry Andric uint64_t break_site_id = m_real_stop_info_sp->GetValue(); 2910b57cec5SDimitry Andric BreakpointSiteSP bp_site_sp; 2925ffd83dbSDimitry Andric bp_site_sp = m_process.GetBreakpointSiteList().FindByID(break_site_id); 2930b57cec5SDimitry Andric if (bp_site_sp) { 2940b57cec5SDimitry Andric uint32_t num_owners = bp_site_sp->GetNumberOfOwners(); 2950b57cec5SDimitry Andric bool is_internal = true; 2960b57cec5SDimitry Andric for (uint32_t i = 0; i < num_owners; i++) { 2970b57cec5SDimitry Andric Breakpoint &bp = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint(); 2989dba64beSDimitry Andric LLDB_LOGF(log, 2999dba64beSDimitry Andric "ThreadPlanCallFunction::PlanExplainsStop: hit " 3000b57cec5SDimitry Andric "breakpoint %d while calling function", 3010b57cec5SDimitry Andric bp.GetID()); 3020b57cec5SDimitry Andric 3030b57cec5SDimitry Andric if (!bp.IsInternal()) { 3040b57cec5SDimitry Andric is_internal = false; 3050b57cec5SDimitry Andric break; 3060b57cec5SDimitry Andric } 3070b57cec5SDimitry Andric } 3080b57cec5SDimitry Andric if (is_internal) { 3099dba64beSDimitry Andric LLDB_LOGF(log, "ThreadPlanCallFunction::PlanExplainsStop hit an " 3100b57cec5SDimitry Andric "internal breakpoint, not stopping."); 3110b57cec5SDimitry Andric return false; 3120b57cec5SDimitry Andric } 3130b57cec5SDimitry Andric } 3140b57cec5SDimitry Andric 3150b57cec5SDimitry Andric if (m_ignore_breakpoints) { 3169dba64beSDimitry Andric LLDB_LOGF(log, 3179dba64beSDimitry Andric "ThreadPlanCallFunction::PlanExplainsStop: we are ignoring " 3180b57cec5SDimitry Andric "breakpoints, overriding breakpoint stop info ShouldStop, " 3190b57cec5SDimitry Andric "returning true"); 3200b57cec5SDimitry Andric m_real_stop_info_sp->OverrideShouldStop(false); 3210b57cec5SDimitry Andric return true; 3220b57cec5SDimitry Andric } else { 3239dba64beSDimitry Andric LLDB_LOGF(log, "ThreadPlanCallFunction::PlanExplainsStop: we are not " 3240b57cec5SDimitry Andric "ignoring breakpoints, overriding breakpoint stop info " 3250b57cec5SDimitry Andric "ShouldStop, returning true"); 3260b57cec5SDimitry Andric m_real_stop_info_sp->OverrideShouldStop(true); 3270b57cec5SDimitry Andric return false; 3280b57cec5SDimitry Andric } 3290b57cec5SDimitry Andric } else if (!m_unwind_on_error) { 3300b57cec5SDimitry Andric // If we don't want to discard this plan, than any stop we don't understand 3310b57cec5SDimitry Andric // should be propagated up the stack. 3320b57cec5SDimitry Andric return false; 3330b57cec5SDimitry Andric } else { 3340b57cec5SDimitry Andric // If the subplan is running, any crashes are attributable to us. If we 3350b57cec5SDimitry Andric // want to discard the plan, then we say we explain the stop but if we are 3360b57cec5SDimitry Andric // going to be discarded, let whoever is above us explain the stop. But 3370b57cec5SDimitry Andric // don't discard the plan if the stop would restart itself (for instance if 3380b57cec5SDimitry Andric // it is a signal that is set not to stop. Check that here first. We just 3390b57cec5SDimitry Andric // say we explain the stop but aren't done and everything will continue on 3400b57cec5SDimitry Andric // from there. 3410b57cec5SDimitry Andric 3420b57cec5SDimitry Andric if (m_real_stop_info_sp && 3430b57cec5SDimitry Andric m_real_stop_info_sp->ShouldStopSynchronous(event_ptr)) { 3440b57cec5SDimitry Andric SetPlanComplete(false); 3450b57cec5SDimitry Andric return m_subplan_sp ? m_unwind_on_error : false; 3460b57cec5SDimitry Andric } else 3470b57cec5SDimitry Andric return true; 3480b57cec5SDimitry Andric } 3490b57cec5SDimitry Andric } 3500b57cec5SDimitry Andric 3510b57cec5SDimitry Andric bool ThreadPlanCallFunction::ShouldStop(Event *event_ptr) { 3520b57cec5SDimitry Andric // We do some computation in DoPlanExplainsStop that may or may not set the 3530b57cec5SDimitry Andric // plan as complete. We need to do that here to make sure our state is 3540b57cec5SDimitry Andric // correct. 3550b57cec5SDimitry Andric DoPlanExplainsStop(event_ptr); 3560b57cec5SDimitry Andric 3570b57cec5SDimitry Andric if (IsPlanComplete()) { 3580b57cec5SDimitry Andric ReportRegisterState("Function completed. Register state was:"); 3590b57cec5SDimitry Andric return true; 3600b57cec5SDimitry Andric } else { 3610b57cec5SDimitry Andric return false; 3620b57cec5SDimitry Andric } 3630b57cec5SDimitry Andric } 3640b57cec5SDimitry Andric 3650b57cec5SDimitry Andric bool ThreadPlanCallFunction::StopOthers() { return m_stop_other_threads; } 3660b57cec5SDimitry Andric 3670b57cec5SDimitry Andric StateType ThreadPlanCallFunction::GetPlanRunState() { return eStateRunning; } 3680b57cec5SDimitry Andric 3690b57cec5SDimitry Andric void ThreadPlanCallFunction::DidPush() { 3700b57cec5SDimitry Andric //#define SINGLE_STEP_EXPRESSIONS 3710b57cec5SDimitry Andric 3720b57cec5SDimitry Andric // Now set the thread state to "no reason" so we don't run with whatever 3730b57cec5SDimitry Andric // signal was outstanding... Wait till the plan is pushed so we aren't 3740b57cec5SDimitry Andric // changing the stop info till we're about to run. 3750b57cec5SDimitry Andric 3760b57cec5SDimitry Andric GetThread().SetStopInfoToNothing(); 3770b57cec5SDimitry Andric 3780b57cec5SDimitry Andric #ifndef SINGLE_STEP_EXPRESSIONS 3795ffd83dbSDimitry Andric Thread &thread = GetThread(); 3805ffd83dbSDimitry Andric m_subplan_sp = std::make_shared<ThreadPlanRunToAddress>(thread, m_start_addr, 3815ffd83dbSDimitry Andric m_stop_other_threads); 3820b57cec5SDimitry Andric 3835ffd83dbSDimitry Andric thread.QueueThreadPlan(m_subplan_sp, false); 3840b57cec5SDimitry Andric m_subplan_sp->SetPrivate(true); 3850b57cec5SDimitry Andric #endif 3860b57cec5SDimitry Andric } 3870b57cec5SDimitry Andric 3880b57cec5SDimitry Andric bool ThreadPlanCallFunction::WillStop() { return true; } 3890b57cec5SDimitry Andric 3900b57cec5SDimitry Andric bool ThreadPlanCallFunction::MischiefManaged() { 39181ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Step); 3920b57cec5SDimitry Andric 3930b57cec5SDimitry Andric if (IsPlanComplete()) { 3949dba64beSDimitry Andric LLDB_LOGF(log, "ThreadPlanCallFunction(%p): Completed call function plan.", 3950b57cec5SDimitry Andric static_cast<void *>(this)); 3960b57cec5SDimitry Andric 3970b57cec5SDimitry Andric ThreadPlan::MischiefManaged(); 3980b57cec5SDimitry Andric return true; 3990b57cec5SDimitry Andric } else { 4000b57cec5SDimitry Andric return false; 4010b57cec5SDimitry Andric } 4020b57cec5SDimitry Andric } 4030b57cec5SDimitry Andric 4040b57cec5SDimitry Andric void ThreadPlanCallFunction::SetBreakpoints() { 4055ffd83dbSDimitry Andric if (m_trap_exceptions) { 4060b57cec5SDimitry Andric m_cxx_language_runtime = 4075ffd83dbSDimitry Andric m_process.GetLanguageRuntime(eLanguageTypeC_plus_plus); 4085ffd83dbSDimitry Andric m_objc_language_runtime = m_process.GetLanguageRuntime(eLanguageTypeObjC); 4090b57cec5SDimitry Andric 4100b57cec5SDimitry Andric if (m_cxx_language_runtime) { 4110b57cec5SDimitry Andric m_should_clear_cxx_exception_bp = 4120b57cec5SDimitry Andric !m_cxx_language_runtime->ExceptionBreakpointsAreSet(); 4130b57cec5SDimitry Andric m_cxx_language_runtime->SetExceptionBreakpoints(); 4140b57cec5SDimitry Andric } 4150b57cec5SDimitry Andric if (m_objc_language_runtime) { 4160b57cec5SDimitry Andric m_should_clear_objc_exception_bp = 4170b57cec5SDimitry Andric !m_objc_language_runtime->ExceptionBreakpointsAreSet(); 4180b57cec5SDimitry Andric m_objc_language_runtime->SetExceptionBreakpoints(); 4190b57cec5SDimitry Andric } 4200b57cec5SDimitry Andric } 4210b57cec5SDimitry Andric } 4220b57cec5SDimitry Andric 4230b57cec5SDimitry Andric void ThreadPlanCallFunction::ClearBreakpoints() { 4240b57cec5SDimitry Andric if (m_trap_exceptions) { 4250b57cec5SDimitry Andric if (m_cxx_language_runtime && m_should_clear_cxx_exception_bp) 4260b57cec5SDimitry Andric m_cxx_language_runtime->ClearExceptionBreakpoints(); 4270b57cec5SDimitry Andric if (m_objc_language_runtime && m_should_clear_objc_exception_bp) 4280b57cec5SDimitry Andric m_objc_language_runtime->ClearExceptionBreakpoints(); 4290b57cec5SDimitry Andric } 4300b57cec5SDimitry Andric } 4310b57cec5SDimitry Andric 4320b57cec5SDimitry Andric bool ThreadPlanCallFunction::BreakpointsExplainStop() { 4330b57cec5SDimitry Andric StopInfoSP stop_info_sp = GetPrivateStopInfo(); 4340b57cec5SDimitry Andric 4350b57cec5SDimitry Andric if (m_trap_exceptions) { 4360b57cec5SDimitry Andric if ((m_cxx_language_runtime && 4370b57cec5SDimitry Andric m_cxx_language_runtime->ExceptionBreakpointsExplainStop( 4380b57cec5SDimitry Andric stop_info_sp)) || 4390b57cec5SDimitry Andric (m_objc_language_runtime && 4400b57cec5SDimitry Andric m_objc_language_runtime->ExceptionBreakpointsExplainStop( 4410b57cec5SDimitry Andric stop_info_sp))) { 44281ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Step); 4439dba64beSDimitry Andric LLDB_LOGF(log, "ThreadPlanCallFunction::BreakpointsExplainStop - Hit an " 4440b57cec5SDimitry Andric "exception breakpoint, setting plan complete."); 4450b57cec5SDimitry Andric 4460b57cec5SDimitry Andric SetPlanComplete(false); 4470b57cec5SDimitry Andric 4480b57cec5SDimitry Andric // If the user has set the ObjC language breakpoint, it would normally 4490b57cec5SDimitry Andric // get priority over our internal catcher breakpoint, but in this case we 4500b57cec5SDimitry Andric // can't let that happen, so force the ShouldStop here. 4510b57cec5SDimitry Andric stop_info_sp->OverrideShouldStop(true); 4520b57cec5SDimitry Andric return true; 4530b57cec5SDimitry Andric } 4540b57cec5SDimitry Andric } 4550b57cec5SDimitry Andric 4560b57cec5SDimitry Andric return false; 4570b57cec5SDimitry Andric } 4580b57cec5SDimitry Andric 4590b57cec5SDimitry Andric void ThreadPlanCallFunction::SetStopOthers(bool new_value) { 4600b57cec5SDimitry Andric m_subplan_sp->SetStopOthers(new_value); 4610b57cec5SDimitry Andric } 4620b57cec5SDimitry Andric 463fe6060f1SDimitry Andric void ThreadPlanCallFunction::RestoreThreadState() { 464fe6060f1SDimitry Andric GetThread().RestoreThreadStateFromCheckpoint(m_stored_thread_state); 4650b57cec5SDimitry Andric } 4660b57cec5SDimitry Andric 4670b57cec5SDimitry Andric void ThreadPlanCallFunction::SetReturnValue() { 4685ffd83dbSDimitry Andric const ABI *abi = m_process.GetABI().get(); 4690b57cec5SDimitry Andric if (abi && m_return_type.IsValid()) { 4700b57cec5SDimitry Andric const bool persistent = false; 4710b57cec5SDimitry Andric m_return_valobj_sp = 4725ffd83dbSDimitry Andric abi->GetReturnValueObject(GetThread(), m_return_type, persistent); 4730b57cec5SDimitry Andric } 4740b57cec5SDimitry Andric } 475