130fdc8d8SChris Lattner //===-- ThreadPlanCallFunction.cpp ------------------------------*- C++ -*-===// 230fdc8d8SChris Lattner // 330fdc8d8SChris Lattner // The LLVM Compiler Infrastructure 430fdc8d8SChris Lattner // 530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source 630fdc8d8SChris Lattner // License. See LICENSE.TXT for details. 730fdc8d8SChris Lattner // 830fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 930fdc8d8SChris Lattner 1030fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanCallFunction.h" 1130fdc8d8SChris Lattner 1230fdc8d8SChris Lattner // C Includes 1330fdc8d8SChris Lattner // C++ Includes 1430fdc8d8SChris Lattner // Other libraries and framework includes 15*46d005dbSJim Ingham 1630fdc8d8SChris Lattner // Project includes 1730fdc8d8SChris Lattner #include "lldb/lldb-private-log.h" 1840d871faSJim Ingham #include "lldb/Breakpoint/Breakpoint.h" 1940d871faSJim Ingham #include "lldb/Breakpoint/BreakpointLocation.h" 2030fdc8d8SChris Lattner #include "lldb/Core/Address.h" 2130fdc8d8SChris Lattner #include "lldb/Core/Log.h" 221f746071SGreg Clayton #include "lldb/Core/Module.h" 2330fdc8d8SChris Lattner #include "lldb/Core/Stream.h" 241f746071SGreg Clayton #include "lldb/Symbol/ObjectFile.h" 25f211510fSSean Callanan #include "lldb/Target/LanguageRuntime.h" 2630fdc8d8SChris Lattner #include "lldb/Target/Process.h" 2730fdc8d8SChris Lattner #include "lldb/Target/RegisterContext.h" 2840d871faSJim Ingham #include "lldb/Target/StopInfo.h" 2930fdc8d8SChris Lattner #include "lldb/Target/Target.h" 3030fdc8d8SChris Lattner #include "lldb/Target/Thread.h" 3130fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanRunToAddress.h" 3230fdc8d8SChris Lattner 3330fdc8d8SChris Lattner using namespace lldb; 3430fdc8d8SChris Lattner using namespace lldb_private; 3530fdc8d8SChris Lattner 3630fdc8d8SChris Lattner //---------------------------------------------------------------------- 3730fdc8d8SChris Lattner // ThreadPlanCallFunction: Plan to call a single function 3830fdc8d8SChris Lattner //---------------------------------------------------------------------- 390092c8ebSJim Ingham bool 400092c8ebSJim Ingham ThreadPlanCallFunction::ConstructorSetup (Thread &thread, 410092c8ebSJim Ingham ABI *& abi, 420092c8ebSJim Ingham lldb::addr_t &start_load_addr, 430092c8ebSJim Ingham lldb::addr_t &function_load_addr) 440092c8ebSJim Ingham { 450092c8ebSJim Ingham SetIsMasterPlan (true); 46923886ceSJim Ingham SetOkayToDiscard (false); 47327c267aSAndrew Kaylor SetPrivate (true); 480092c8ebSJim Ingham 490092c8ebSJim Ingham ProcessSP process_sp (thread.GetProcess()); 500092c8ebSJim Ingham if (!process_sp) 510092c8ebSJim Ingham return false; 520092c8ebSJim Ingham 530092c8ebSJim Ingham abi = process_sp->GetABI().get(); 540092c8ebSJim Ingham 550092c8ebSJim Ingham if (!abi) 560092c8ebSJim Ingham return false; 570092c8ebSJim Ingham 585160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP)); 590092c8ebSJim Ingham 600092c8ebSJim Ingham SetBreakpoints(); 610092c8ebSJim Ingham 620092c8ebSJim Ingham m_function_sp = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize(); 630092c8ebSJim Ingham // If we can't read memory at the point of the process where we are planning to put our function, we're 640092c8ebSJim Ingham // not going to get any further... 650092c8ebSJim Ingham Error error; 660092c8ebSJim Ingham process_sp->ReadUnsignedIntegerFromMemory(m_function_sp, 4, 0, error); 670092c8ebSJim Ingham if (!error.Success()) 680092c8ebSJim Ingham { 69ea06f3bfSJim Ingham m_constructor_errors.Printf ("Trying to put the stack in unreadable memory at: 0x%" PRIx64 ".", m_function_sp); 700092c8ebSJim Ingham if (log) 71ea06f3bfSJim Ingham log->Printf ("ThreadPlanCallFunction(%p): %s.", this, m_constructor_errors.GetData()); 720092c8ebSJim Ingham return false; 730092c8ebSJim Ingham } 740092c8ebSJim Ingham 756fbc48bcSJim Ingham Module *exe_module = GetTarget().GetExecutableModulePointer(); 760092c8ebSJim Ingham 770092c8ebSJim Ingham if (exe_module == NULL) 780092c8ebSJim Ingham { 79ea06f3bfSJim Ingham m_constructor_errors.Printf ("Can't execute code without an executable module."); 800092c8ebSJim Ingham if (log) 81ea06f3bfSJim Ingham log->Printf ("ThreadPlanCallFunction(%p): %s.", this, m_constructor_errors.GetData()); 820092c8ebSJim Ingham return false; 830092c8ebSJim Ingham } 840092c8ebSJim Ingham else 850092c8ebSJim Ingham { 860092c8ebSJim Ingham ObjectFile *objectFile = exe_module->GetObjectFile(); 870092c8ebSJim Ingham if (!objectFile) 880092c8ebSJim Ingham { 89ea06f3bfSJim Ingham m_constructor_errors.Printf ("Could not find object file for module \"%s\".", 90ea06f3bfSJim Ingham exe_module->GetFileSpec().GetFilename().AsCString()); 91ea06f3bfSJim Ingham 920092c8ebSJim Ingham if (log) 93ea06f3bfSJim Ingham log->Printf ("ThreadPlanCallFunction(%p): %s.", this, m_constructor_errors.GetData()); 940092c8ebSJim Ingham return false; 950092c8ebSJim Ingham } 96ea06f3bfSJim Ingham 970092c8ebSJim Ingham m_start_addr = objectFile->GetEntryPointAddress(); 980092c8ebSJim Ingham if (!m_start_addr.IsValid()) 990092c8ebSJim Ingham { 100ea06f3bfSJim Ingham m_constructor_errors.Printf ("Could not find entry point address for executable module \"%s\".", 101ea06f3bfSJim Ingham exe_module->GetFileSpec().GetFilename().AsCString()); 1020092c8ebSJim Ingham if (log) 103ea06f3bfSJim Ingham log->Printf ("ThreadPlanCallFunction(%p): %s.", this, m_constructor_errors.GetData()); 1040092c8ebSJim Ingham return false; 1050092c8ebSJim Ingham } 1060092c8ebSJim Ingham } 1070092c8ebSJim Ingham 1086fbc48bcSJim Ingham start_load_addr = m_start_addr.GetLoadAddress (&GetTarget()); 1090092c8ebSJim Ingham 1100092c8ebSJim Ingham // Checkpoint the thread state so we can restore it later. 1110092c8ebSJim Ingham if (log && log->GetVerbose()) 1120092c8ebSJim Ingham ReportRegisterState ("About to checkpoint thread before function call. Original register state was:"); 1130092c8ebSJim Ingham 1140092c8ebSJim Ingham if (!thread.CheckpointThreadState (m_stored_thread_state)) 1150092c8ebSJim Ingham { 116ea06f3bfSJim Ingham m_constructor_errors.Printf ("Setting up ThreadPlanCallFunction, failed to checkpoint thread state."); 1170092c8ebSJim Ingham if (log) 118ea06f3bfSJim Ingham log->Printf ("ThreadPlanCallFunction(%p): %s.", this, m_constructor_errors.GetData()); 1190092c8ebSJim Ingham return false; 1200092c8ebSJim Ingham } 1216fbc48bcSJim Ingham function_load_addr = m_function_addr.GetLoadAddress (&GetTarget()); 1220092c8ebSJim Ingham 1230092c8ebSJim Ingham return true; 1240092c8ebSJim Ingham } 12530fdc8d8SChris Lattner 12630fdc8d8SChris Lattner ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread, 12700049b8bSMatt Kopec const Address &function, 128ef651600SJim Ingham const ClangASTType &return_type, 129a464f3d4SSean Callanan llvm::ArrayRef<addr_t> args, 130a464f3d4SSean Callanan const EvaluateExpressionOptions &options) : 131b01e742aSJim Ingham ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion), 13230fdc8d8SChris Lattner m_valid (false), 1336fbc48bcSJim Ingham m_stop_other_threads (options.GetStopOthers()), 1346fbc48bcSJim Ingham m_unwind_on_error (options.DoesUnwindOnError()), 1356fbc48bcSJim Ingham m_ignore_breakpoints (options.DoesIgnoreBreakpoints()), 1366fbc48bcSJim Ingham m_debug_execution (options.GetDebug()), 1376fbc48bcSJim Ingham m_trap_exceptions (options.GetTrapExceptions()), 13816e0c686SJim Ingham m_function_addr (function), 139b4cb0be3SFilipe Cabecinhas m_function_sp (0), 140ef651600SJim Ingham m_return_type (return_type), 141ce553d88SJim Ingham m_takedown_done (false), 1426fbc48bcSJim Ingham m_should_clear_objc_exception_bp(false), 1436fbc48bcSJim Ingham m_should_clear_cxx_exception_bp (false), 1446fbc48bcSJim Ingham m_stop_address (LLDB_INVALID_ADDRESS) 14530fdc8d8SChris Lattner { 1460092c8ebSJim Ingham lldb::addr_t start_load_addr; 1470092c8ebSJim Ingham ABI *abi; 1480092c8ebSJim Ingham lldb::addr_t function_load_addr; 149923886ceSJim Ingham if (!ConstructorSetup (thread, abi, start_load_addr, function_load_addr)) 1501ac04c30SGreg Clayton return; 1511ac04c30SGreg Clayton 15230fdc8d8SChris Lattner if (!abi->PrepareTrivialCall(thread, 153e359d9b7SSean Callanan m_function_sp, 1540092c8ebSJim Ingham function_load_addr, 1552a48f525SGreg Clayton start_load_addr, 156a464f3d4SSean Callanan args)) 15730fdc8d8SChris Lattner return; 15830fdc8d8SChris Lattner 1599da3683cSJim Ingham ReportRegisterState ("Function call was set up. Register state was:"); 1609da3683cSJim Ingham 1619da3683cSJim Ingham m_valid = true; 1629da3683cSJim Ingham } 1639da3683cSJim Ingham 1649da3683cSJim Ingham ThreadPlanCallFunction::~ThreadPlanCallFunction () 1659da3683cSJim Ingham { 1660161b49cSJim Ingham DoTakedown(PlanSucceeded()); 1679da3683cSJim Ingham } 1689da3683cSJim Ingham 1699da3683cSJim Ingham void 1709da3683cSJim Ingham ThreadPlanCallFunction::ReportRegisterState (const char *message) 1719da3683cSJim Ingham { 1725160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP | LIBLLDB_LOG_VERBOSE)); 173ece96492SSean Callanan if (log) 174ece96492SSean Callanan { 175af247d7bSGreg Clayton StreamString strm; 1765ccbd294SGreg Clayton RegisterContext *reg_ctx = m_thread.GetRegisterContext().get(); 177ece96492SSean Callanan 1789da3683cSJim Ingham log->PutCString(message); 179ece96492SSean Callanan 180af247d7bSGreg Clayton RegisterValue reg_value; 181ece96492SSean Callanan 182af247d7bSGreg Clayton for (uint32_t reg_idx = 0, num_registers = reg_ctx->GetRegisterCount(); 183af247d7bSGreg Clayton reg_idx < num_registers; 184af247d7bSGreg Clayton ++reg_idx) 185af247d7bSGreg Clayton { 186af247d7bSGreg Clayton const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex (reg_idx); 187af247d7bSGreg Clayton if (reg_ctx->ReadRegister(reg_info, reg_value)) 188af247d7bSGreg Clayton { 189af247d7bSGreg Clayton reg_value.Dump(&strm, reg_info, true, false, eFormatDefault); 190af247d7bSGreg Clayton strm.EOL(); 191ece96492SSean Callanan } 192ece96492SSean Callanan } 193af247d7bSGreg Clayton log->PutCString(strm.GetData()); 194af247d7bSGreg Clayton } 19510af7c43SSean Callanan } 19610af7c43SSean Callanan 19710af7c43SSean Callanan void 19818de2fdcSJim Ingham ThreadPlanCallFunction::DoTakedown (bool success) 19910af7c43SSean Callanan { 2005160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP)); 20187d0e618SJim Ingham 20287d0e618SJim Ingham if (!m_valid) 20387d0e618SJim Ingham { 20487d0e618SJim Ingham //Don't call DoTakedown if we were never valid to begin with. 20587d0e618SJim Ingham if (log) 20687d0e618SJim Ingham log->Printf ("ThreadPlanCallFunction(%p): Log called on ThreadPlanCallFunction that was never valid.", this); 20787d0e618SJim Ingham return; 20887d0e618SJim Ingham } 20987d0e618SJim Ingham 2109da3683cSJim Ingham if (!m_takedown_done) 21177787033SJim Ingham { 21218de2fdcSJim Ingham if (success) 21318de2fdcSJim Ingham { 2141ac04c30SGreg Clayton ProcessSP process_sp (m_thread.GetProcess()); 2151ac04c30SGreg Clayton const ABI *abi = process_sp ? process_sp->GetABI().get() : NULL; 216ef651600SJim Ingham if (abi && m_return_type.IsValid()) 217ef651600SJim Ingham { 2186153c518SSean Callanan const bool persistent = false; 2196153c518SSean Callanan m_return_valobj_sp = abi->GetReturnValueObject (m_thread, m_return_type, persistent); 22070b57657SGreg Clayton } 22118de2fdcSJim Ingham } 2229da3683cSJim Ingham if (log) 223d01b2953SDaniel Malea log->Printf ("ThreadPlanCallFunction(%p): DoTakedown called for thread 0x%4.4" PRIx64 ", m_valid: %d complete: %d.\n", this, m_thread.GetID(), m_valid, IsPlanComplete()); 2249da3683cSJim Ingham m_takedown_done = true; 225ce553d88SJim Ingham m_stop_address = m_thread.GetStackFrameAtIndex(0)->GetRegisterContext()->GetPC(); 22660c4118cSJim Ingham m_real_stop_info_sp = GetPrivateStopInfo (); 2277b24e95eSEd Maste if (!m_thread.RestoreRegisterStateFromCheckpoint(m_stored_thread_state)) 2287b24e95eSEd Maste { 2297b24e95eSEd Maste if (log) 2307b24e95eSEd Maste log->Printf("ThreadPlanCallFunction(%p): DoTakedown failed to restore register state", this); 2317b24e95eSEd Maste } 23218de2fdcSJim Ingham SetPlanComplete(success); 23310af7c43SSean Callanan ClearBreakpoints(); 2349da3683cSJim Ingham if (log && log->GetVerbose()) 2359da3683cSJim Ingham ReportRegisterState ("Restoring thread state after function call. Restored register state:"); 2362c36439cSJim Ingham 2379da3683cSJim Ingham } 2389da3683cSJim Ingham else 2399da3683cSJim Ingham { 2409da3683cSJim Ingham if (log) 241d01b2953SDaniel Malea log->Printf ("ThreadPlanCallFunction(%p): DoTakedown called as no-op for thread 0x%4.4" PRIx64 ", m_valid: %d complete: %d.\n", this, m_thread.GetID(), m_valid, IsPlanComplete()); 24230fdc8d8SChris Lattner } 24377787033SJim Ingham } 24430fdc8d8SChris Lattner 24530fdc8d8SChris Lattner void 246bda4e5ebSJim Ingham ThreadPlanCallFunction::WillPop () 247bda4e5ebSJim Ingham { 2480161b49cSJim Ingham DoTakedown(PlanSucceeded()); 249bda4e5ebSJim Ingham } 250bda4e5ebSJim Ingham 251bda4e5ebSJim Ingham void 2522a48f525SGreg Clayton ThreadPlanCallFunction::GetDescription (Stream *s, DescriptionLevel level) 25330fdc8d8SChris Lattner { 2542a48f525SGreg Clayton if (level == eDescriptionLevelBrief) 25530fdc8d8SChris Lattner { 25630fdc8d8SChris Lattner s->Printf("Function call thread plan"); 25730fdc8d8SChris Lattner } 25830fdc8d8SChris Lattner else 25930fdc8d8SChris Lattner { 2601ac04c30SGreg Clayton TargetSP target_sp (m_thread.CalculateTarget()); 261d01b2953SDaniel Malea s->Printf("Thread plan to call 0x%" PRIx64, m_function_addr.GetLoadAddress(target_sp.get())); 26230fdc8d8SChris Lattner } 26330fdc8d8SChris Lattner } 26430fdc8d8SChris Lattner 26530fdc8d8SChris Lattner bool 26630fdc8d8SChris Lattner ThreadPlanCallFunction::ValidatePlan (Stream *error) 26730fdc8d8SChris Lattner { 26830fdc8d8SChris Lattner if (!m_valid) 269ea06f3bfSJim Ingham { 270ea06f3bfSJim Ingham if (error) 271ea06f3bfSJim Ingham { 272ea06f3bfSJim Ingham if (m_constructor_errors.GetSize() > 0) 273ea06f3bfSJim Ingham error->PutCString (m_constructor_errors.GetData()); 274ea06f3bfSJim Ingham else 275ea06f3bfSJim Ingham error->PutCString ("Unknown error"); 276ea06f3bfSJim Ingham } 27730fdc8d8SChris Lattner return false; 278ea06f3bfSJim Ingham } 27930fdc8d8SChris Lattner 28030fdc8d8SChris Lattner return true; 28130fdc8d8SChris Lattner } 28230fdc8d8SChris Lattner 2830161b49cSJim Ingham 2840161b49cSJim Ingham Vote 2850161b49cSJim Ingham ThreadPlanCallFunction::ShouldReportStop(Event *event_ptr) 28630fdc8d8SChris Lattner { 2870161b49cSJim Ingham if (m_takedown_done || IsPlanComplete()) 2880161b49cSJim Ingham return eVoteYes; 2890161b49cSJim Ingham else 2900161b49cSJim Ingham return ThreadPlan::ShouldReportStop(event_ptr); 2910161b49cSJim Ingham } 2920161b49cSJim Ingham 2930161b49cSJim Ingham bool 294221d51cfSJim Ingham ThreadPlanCallFunction::DoPlanExplainsStop (Event *event_ptr) 2950161b49cSJim Ingham { 2965160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP|LIBLLDB_LOG_PROCESS)); 29760c4118cSJim Ingham m_real_stop_info_sp = GetPrivateStopInfo (); 298160f78c5SJim Ingham 29940d871faSJim Ingham // If our subplan knows why we stopped, even if it's done (which would forward the question to us) 30040d871faSJim Ingham // we answer yes. 3010161b49cSJim Ingham if (m_subplan_sp.get() != NULL && m_subplan_sp->PlanExplainsStop(event_ptr)) 302184e9811SJim Ingham { 303184e9811SJim Ingham SetPlanComplete(); 30440d871faSJim Ingham return true; 305184e9811SJim Ingham } 3063e6fedcaSSean Callanan 307c98aca60SSean Callanan // Check if the breakpoint is one of ours. 308c98aca60SSean Callanan 30918de2fdcSJim Ingham StopReason stop_reason; 31018de2fdcSJim Ingham if (!m_real_stop_info_sp) 31118de2fdcSJim Ingham stop_reason = eStopReasonNone; 31218de2fdcSJim Ingham else 31318de2fdcSJim Ingham stop_reason = m_real_stop_info_sp->GetStopReason(); 3140161b49cSJim Ingham if (log) 3150161b49cSJim Ingham log->Printf ("ThreadPlanCallFunction::PlanExplainsStop: Got stop reason - %s.", Thread::StopReasonAsCString(stop_reason)); 31618de2fdcSJim Ingham 31718de2fdcSJim Ingham if (stop_reason == eStopReasonBreakpoint && BreakpointsExplainStop()) 318c98aca60SSean Callanan return true; 319c98aca60SSean Callanan 3200161b49cSJim Ingham // We control breakpoints separately from other "stop reasons." So first, 3210161b49cSJim Ingham // check the case where we stopped for an internal breakpoint, in that case, continue on. 3220161b49cSJim Ingham // If it is not an internal breakpoint, consult m_ignore_breakpoints. 3236db73ca5SSean Callanan 32418de2fdcSJim Ingham 32518de2fdcSJim Ingham if (stop_reason == eStopReasonBreakpoint) 32640d871faSJim Ingham { 3271ac04c30SGreg Clayton ProcessSP process_sp (m_thread.CalculateProcess()); 328160f78c5SJim Ingham uint64_t break_site_id = m_real_stop_info_sp->GetValue(); 3291ac04c30SGreg Clayton BreakpointSiteSP bp_site_sp; 3301ac04c30SGreg Clayton if (process_sp) 3311ac04c30SGreg Clayton bp_site_sp = process_sp->GetBreakpointSiteList().FindByID(break_site_id); 33240d871faSJim Ingham if (bp_site_sp) 33340d871faSJim Ingham { 33440d871faSJim Ingham uint32_t num_owners = bp_site_sp->GetNumberOfOwners(); 33540d871faSJim Ingham bool is_internal = true; 33640d871faSJim Ingham for (uint32_t i = 0; i < num_owners; i++) 33740d871faSJim Ingham { 3386db73ca5SSean Callanan Breakpoint &bp = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint(); 3390161b49cSJim Ingham if (log) 3400161b49cSJim Ingham log->Printf ("ThreadPlanCallFunction::PlanExplainsStop: hit breakpoint %d while calling function", bp.GetID()); 3416db73ca5SSean Callanan 3426db73ca5SSean Callanan if (!bp.IsInternal()) 34340d871faSJim Ingham { 34440d871faSJim Ingham is_internal = false; 34540d871faSJim Ingham break; 34640d871faSJim Ingham } 34740d871faSJim Ingham } 34840d871faSJim Ingham if (is_internal) 3490161b49cSJim Ingham { 3500161b49cSJim Ingham if (log) 3510161b49cSJim Ingham log->Printf ("ThreadPlanCallFunction::PlanExplainsStop hit an internal breakpoint, not stopping."); 35240d871faSJim Ingham return false; 35340d871faSJim Ingham } 3540161b49cSJim Ingham } 35540d871faSJim Ingham 356184e9811SJim Ingham if (m_ignore_breakpoints) 357923886ceSJim Ingham { 3580161b49cSJim Ingham if (log) 3590161b49cSJim Ingham log->Printf("ThreadPlanCallFunction::PlanExplainsStop: we are ignoring breakpoints, overriding breakpoint stop info ShouldStop, returning true"); 3600161b49cSJim Ingham m_real_stop_info_sp->OverrideShouldStop(false); 361923886ceSJim Ingham return true; 362923886ceSJim Ingham } 363923886ceSJim Ingham else 3640161b49cSJim Ingham { 3650161b49cSJim Ingham if (log) 3660161b49cSJim Ingham log->Printf("ThreadPlanCallFunction::PlanExplainsStop: we are not ignoring breakpoints, overriding breakpoint stop info ShouldStop, returning true"); 3670161b49cSJim Ingham m_real_stop_info_sp->OverrideShouldStop(true); 3680161b49cSJim Ingham return false; 3690161b49cSJim Ingham } 3700161b49cSJim Ingham } 3710161b49cSJim Ingham else if (!m_unwind_on_error) 3720161b49cSJim Ingham { 3730161b49cSJim Ingham // If we don't want to discard this plan, than any stop we don't understand should be propagated up the stack. 374923886ceSJim Ingham return false; 37540d871faSJim Ingham } 37640d871faSJim Ingham else 37740d871faSJim Ingham { 37840d871faSJim Ingham // If the subplan is running, any crashes are attributable to us. 3792c36439cSJim Ingham // If we want to discard the plan, then we say we explain the stop 3802c36439cSJim Ingham // but if we are going to be discarded, let whoever is above us 3812c36439cSJim Ingham // explain the stop. 3820161b49cSJim Ingham // But don't discard the plan if the stop would restart itself (for instance if it is a 3830161b49cSJim Ingham // signal that is set not to stop. Check that here first. We just say we explain the stop 3840161b49cSJim Ingham // but aren't done and everything will continue on from there. 3850161b49cSJim Ingham 3860161b49cSJim Ingham if (m_real_stop_info_sp->ShouldStopSynchronous(event_ptr)) 3870161b49cSJim Ingham { 388184e9811SJim Ingham SetPlanComplete(false); 3899a028519SSean Callanan if (m_subplan_sp) 39018de2fdcSJim Ingham { 391184e9811SJim Ingham if (m_unwind_on_error) 39218de2fdcSJim Ingham return true; 39318de2fdcSJim Ingham else 39418de2fdcSJim Ingham return false; 39518de2fdcSJim Ingham } 39618de2fdcSJim Ingham else 39718de2fdcSJim Ingham return false; 39830fdc8d8SChris Lattner } 3990161b49cSJim Ingham else 4000161b49cSJim Ingham return true; 4010161b49cSJim Ingham } 40240d871faSJim Ingham } 40330fdc8d8SChris Lattner 40430fdc8d8SChris Lattner bool 40530fdc8d8SChris Lattner ThreadPlanCallFunction::ShouldStop (Event *event_ptr) 40630fdc8d8SChris Lattner { 407221d51cfSJim Ingham // We do some computation in DoPlanExplainsStop that may or may not set the plan as complete. 408184e9811SJim Ingham // We need to do that here to make sure our state is correct. 409221d51cfSJim Ingham DoPlanExplainsStop(event_ptr); 410184e9811SJim Ingham 411184e9811SJim Ingham if (IsPlanComplete()) 41230fdc8d8SChris Lattner { 4139da3683cSJim Ingham ReportRegisterState ("Function completed. Register state was:"); 41430fdc8d8SChris Lattner return true; 41530fdc8d8SChris Lattner } 41630fdc8d8SChris Lattner else 41730fdc8d8SChris Lattner { 41830fdc8d8SChris Lattner return false; 41930fdc8d8SChris Lattner } 42030fdc8d8SChris Lattner } 42130fdc8d8SChris Lattner 42230fdc8d8SChris Lattner bool 42330fdc8d8SChris Lattner ThreadPlanCallFunction::StopOthers () 42430fdc8d8SChris Lattner { 42530fdc8d8SChris Lattner return m_stop_other_threads; 42630fdc8d8SChris Lattner } 42730fdc8d8SChris Lattner 42830fdc8d8SChris Lattner StateType 42906e827ccSJim Ingham ThreadPlanCallFunction::GetPlanRunState () 43030fdc8d8SChris Lattner { 43130fdc8d8SChris Lattner return eStateRunning; 43230fdc8d8SChris Lattner } 43330fdc8d8SChris Lattner 43430fdc8d8SChris Lattner void 43530fdc8d8SChris Lattner ThreadPlanCallFunction::DidPush () 43630fdc8d8SChris Lattner { 437be3a1b14SSean Callanan //#define SINGLE_STEP_EXPRESSIONS 438be3a1b14SSean Callanan 4398559a355SJim Ingham // Now set the thread state to "no reason" so we don't run with whatever signal was outstanding... 4408559a355SJim Ingham // Wait till the plan is pushed so we aren't changing the stop info till we're about to run. 4418559a355SJim Ingham 4428559a355SJim Ingham GetThread().SetStopInfoToNothing(); 4438559a355SJim Ingham 444be3a1b14SSean Callanan #ifndef SINGLE_STEP_EXPRESSIONS 44530fdc8d8SChris Lattner m_subplan_sp.reset(new ThreadPlanRunToAddress(m_thread, m_start_addr, m_stop_other_threads)); 44630fdc8d8SChris Lattner 44730fdc8d8SChris Lattner m_thread.QueueThreadPlan(m_subplan_sp, false); 44877787033SJim Ingham m_subplan_sp->SetPrivate (true); 449be3a1b14SSean Callanan #endif 45030fdc8d8SChris Lattner } 45130fdc8d8SChris Lattner 45230fdc8d8SChris Lattner bool 45330fdc8d8SChris Lattner ThreadPlanCallFunction::WillStop () 45430fdc8d8SChris Lattner { 45530fdc8d8SChris Lattner return true; 45630fdc8d8SChris Lattner } 45730fdc8d8SChris Lattner 45830fdc8d8SChris Lattner bool 45930fdc8d8SChris Lattner ThreadPlanCallFunction::MischiefManaged () 46030fdc8d8SChris Lattner { 4615160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 46230fdc8d8SChris Lattner 463184e9811SJim Ingham if (IsPlanComplete()) 464184e9811SJim Ingham { 46530fdc8d8SChris Lattner if (log) 46687d0e618SJim Ingham log->Printf("ThreadPlanCallFunction(%p): Completed call function plan.", this); 46730fdc8d8SChris Lattner 46830fdc8d8SChris Lattner ThreadPlan::MischiefManaged (); 46930fdc8d8SChris Lattner return true; 47030fdc8d8SChris Lattner } 47130fdc8d8SChris Lattner else 47230fdc8d8SChris Lattner { 47330fdc8d8SChris Lattner return false; 47430fdc8d8SChris Lattner } 47530fdc8d8SChris Lattner } 4766db73ca5SSean Callanan 4776db73ca5SSean Callanan void 4786db73ca5SSean Callanan ThreadPlanCallFunction::SetBreakpoints () 4796db73ca5SSean Callanan { 4801ac04c30SGreg Clayton ProcessSP process_sp (m_thread.CalculateProcess()); 4816fbc48bcSJim Ingham if (m_trap_exceptions && process_sp) 4821ac04c30SGreg Clayton { 4831ac04c30SGreg Clayton m_cxx_language_runtime = process_sp->GetLanguageRuntime(eLanguageTypeC_plus_plus); 4841ac04c30SGreg Clayton m_objc_language_runtime = process_sp->GetLanguageRuntime(eLanguageTypeObjC); 4856db73ca5SSean Callanan 486f211510fSSean Callanan if (m_cxx_language_runtime) 4876fbc48bcSJim Ingham { 4886fbc48bcSJim Ingham m_should_clear_cxx_exception_bp = !m_cxx_language_runtime->ExceptionBreakpointsAreSet(); 489f211510fSSean Callanan m_cxx_language_runtime->SetExceptionBreakpoints(); 4906fbc48bcSJim Ingham } 491f211510fSSean Callanan if (m_objc_language_runtime) 4926fbc48bcSJim Ingham { 4936fbc48bcSJim Ingham m_should_clear_objc_exception_bp = !m_objc_language_runtime->ExceptionBreakpointsAreSet(); 494f211510fSSean Callanan m_objc_language_runtime->SetExceptionBreakpoints(); 4956db73ca5SSean Callanan } 4961ac04c30SGreg Clayton } 4976fbc48bcSJim Ingham } 4986db73ca5SSean Callanan 4996db73ca5SSean Callanan void 5006db73ca5SSean Callanan ThreadPlanCallFunction::ClearBreakpoints () 5016db73ca5SSean Callanan { 5026fbc48bcSJim Ingham if (m_trap_exceptions) 5036fbc48bcSJim Ingham { 5046fbc48bcSJim Ingham if (m_cxx_language_runtime && m_should_clear_cxx_exception_bp) 505f211510fSSean Callanan m_cxx_language_runtime->ClearExceptionBreakpoints(); 5066fbc48bcSJim Ingham if (m_objc_language_runtime && m_should_clear_objc_exception_bp) 507f211510fSSean Callanan m_objc_language_runtime->ClearExceptionBreakpoints(); 5086db73ca5SSean Callanan } 5096fbc48bcSJim Ingham } 510c98aca60SSean Callanan 511c98aca60SSean Callanan bool 512c98aca60SSean Callanan ThreadPlanCallFunction::BreakpointsExplainStop() 513c98aca60SSean Callanan { 51460c4118cSJim Ingham StopInfoSP stop_info_sp = GetPrivateStopInfo (); 515c98aca60SSean Callanan 5166fbc48bcSJim Ingham if (m_trap_exceptions) 5176fbc48bcSJim Ingham { 518184e9811SJim Ingham if ((m_cxx_language_runtime && 519f211510fSSean Callanan m_cxx_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp)) 520184e9811SJim Ingham ||(m_objc_language_runtime && 521184e9811SJim Ingham m_objc_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp))) 522184e9811SJim Ingham { 523641a67ceSJim Ingham Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP)); 524641a67ceSJim Ingham if (log) 525641a67ceSJim Ingham log->Printf ("ThreadPlanCallFunction::BreakpointsExplainStop - Hit an exception breakpoint, setting plan complete."); 526641a67ceSJim Ingham 527184e9811SJim Ingham SetPlanComplete(false); 528641a67ceSJim Ingham 529641a67ceSJim Ingham // If the user has set the ObjC language breakpoint, it would normally get priority over our internal 530641a67ceSJim Ingham // catcher breakpoint, but in this case we can't let that happen, so force the ShouldStop here. 531641a67ceSJim Ingham stop_info_sp->OverrideShouldStop (true); 532c98aca60SSean Callanan return true; 533184e9811SJim Ingham } 5346fbc48bcSJim Ingham } 535f211510fSSean Callanan 536c98aca60SSean Callanan return false; 537c98aca60SSean Callanan } 5388559a355SJim Ingham 5390ff099f1SJim Ingham void 5400ff099f1SJim Ingham ThreadPlanCallFunction::SetStopOthers (bool new_value) 5410ff099f1SJim Ingham { 5420ff099f1SJim Ingham m_subplan_sp->SetStopOthers(new_value); 5430ff099f1SJim Ingham } 5440ff099f1SJim Ingham 5450ff099f1SJim Ingham 5468559a355SJim Ingham bool 5478559a355SJim Ingham ThreadPlanCallFunction::RestoreThreadState() 5488559a355SJim Ingham { 5498559a355SJim Ingham return GetThread().RestoreThreadStateFromCheckpoint(m_stored_thread_state); 5508559a355SJim Ingham } 5518559a355SJim Ingham 552