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 156db73ca5SSean Callanan #include "llvm/Support/MachO.h" 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" 2230fdc8d8SChris Lattner #include "lldb/Core/Stream.h" 23f211510fSSean Callanan #include "lldb/Target/LanguageRuntime.h" 2430fdc8d8SChris Lattner #include "lldb/Target/Process.h" 2530fdc8d8SChris Lattner #include "lldb/Target/RegisterContext.h" 2640d871faSJim Ingham #include "lldb/Target/StopInfo.h" 2730fdc8d8SChris Lattner #include "lldb/Target/Target.h" 2830fdc8d8SChris Lattner #include "lldb/Target/Thread.h" 2930fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanRunToAddress.h" 3030fdc8d8SChris Lattner 3130fdc8d8SChris Lattner using namespace lldb; 3230fdc8d8SChris Lattner using namespace lldb_private; 3330fdc8d8SChris Lattner 3430fdc8d8SChris Lattner //---------------------------------------------------------------------- 3530fdc8d8SChris Lattner // ThreadPlanCallFunction: Plan to call a single function 3630fdc8d8SChris Lattner //---------------------------------------------------------------------- 3730fdc8d8SChris Lattner 3830fdc8d8SChris Lattner ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread, 3930fdc8d8SChris Lattner Address &function, 4030fdc8d8SChris Lattner lldb::addr_t arg, 4130fdc8d8SChris Lattner bool stop_other_threads, 42fc55f5d1SSean Callanan bool discard_on_error, 43fc55f5d1SSean Callanan lldb::addr_t *this_arg) : 44b01e742aSJim Ingham ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion), 4530fdc8d8SChris Lattner m_valid (false), 461ee0d4f7SBenjamin Kramer m_stop_other_threads (stop_other_threads), 4730fdc8d8SChris Lattner m_arg_addr (arg), 4830fdc8d8SChris Lattner m_args (NULL), 491ee0d4f7SBenjamin Kramer m_process (thread.GetProcess()), 501ee0d4f7SBenjamin Kramer m_thread (thread) 5130fdc8d8SChris Lattner { 5230fdc8d8SChris Lattner SetOkayToDiscard (discard_on_error); 5330fdc8d8SChris Lattner 5430fdc8d8SChris Lattner Process& process = thread.GetProcess(); 5530fdc8d8SChris Lattner Target& target = process.GetTarget(); 5630fdc8d8SChris Lattner const ABI *abi = process.GetABI(); 5730fdc8d8SChris Lattner 5830fdc8d8SChris Lattner if (!abi) 5930fdc8d8SChris Lattner return; 6030fdc8d8SChris Lattner 616db73ca5SSean Callanan SetBreakpoints(); 626db73ca5SSean Callanan 6330fdc8d8SChris Lattner lldb::addr_t spBelowRedZone = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize(); 6430fdc8d8SChris Lattner 6530fdc8d8SChris Lattner SymbolContextList contexts; 6630fdc8d8SChris Lattner SymbolContext context; 6730fdc8d8SChris Lattner ModuleSP executableModuleSP (target.GetExecutableModule()); 6830fdc8d8SChris Lattner 6930fdc8d8SChris Lattner if (!executableModuleSP || 7030fdc8d8SChris Lattner !executableModuleSP->FindSymbolsWithNameAndType(ConstString ("start"), eSymbolTypeCode, contexts)) 7130fdc8d8SChris Lattner return; 7230fdc8d8SChris Lattner 7330fdc8d8SChris Lattner contexts.GetContextAtIndex(0, context); 7430fdc8d8SChris Lattner 7530fdc8d8SChris Lattner m_start_addr = context.symbol->GetValue(); 76f5e56de0SGreg Clayton lldb::addr_t StartLoadAddr = m_start_addr.GetLoadAddress(&target); 7730fdc8d8SChris Lattner 7830fdc8d8SChris Lattner if (!thread.SaveFrameZeroState(m_register_backup)) 7930fdc8d8SChris Lattner return; 8030fdc8d8SChris Lattner 8130fdc8d8SChris Lattner m_function_addr = function; 82f5e56de0SGreg Clayton lldb::addr_t FunctionLoadAddr = m_function_addr.GetLoadAddress(&target); 8330fdc8d8SChris Lattner 8430fdc8d8SChris Lattner if (!abi->PrepareTrivialCall(thread, 8530fdc8d8SChris Lattner spBelowRedZone, 8630fdc8d8SChris Lattner FunctionLoadAddr, 8730fdc8d8SChris Lattner StartLoadAddr, 88fc55f5d1SSean Callanan m_arg_addr, 89fc55f5d1SSean Callanan this_arg)) 9030fdc8d8SChris Lattner return; 9130fdc8d8SChris Lattner 92ece96492SSean Callanan LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 93ece96492SSean Callanan 94ece96492SSean Callanan if (log) 95ece96492SSean Callanan { 96ece96492SSean Callanan RegisterContext *reg_ctx = m_thread.GetRegisterContext(); 97ece96492SSean Callanan 98ece96492SSean Callanan log->PutCString("Function call was set up. Register state was:"); 99ece96492SSean Callanan 100ece96492SSean Callanan for (uint32_t register_index = 0, num_registers = reg_ctx->GetRegisterCount(); 101ece96492SSean Callanan register_index < num_registers; 102ece96492SSean Callanan ++register_index) 103ece96492SSean Callanan { 104ece96492SSean Callanan const char *register_name = reg_ctx->GetRegisterName(register_index); 105ece96492SSean Callanan uint64_t register_value = reg_ctx->ReadRegisterAsUnsigned(register_index, LLDB_INVALID_ADDRESS); 106ece96492SSean Callanan 107ece96492SSean Callanan log->Printf(" %s = 0x%llx", register_name, register_value); 108ece96492SSean Callanan } 109ece96492SSean Callanan } 110ece96492SSean Callanan 11130fdc8d8SChris Lattner m_valid = true; 11230fdc8d8SChris Lattner } 11330fdc8d8SChris Lattner 11430fdc8d8SChris Lattner ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread, 11530fdc8d8SChris Lattner Address &function, 11630fdc8d8SChris Lattner ValueList &args, 11730fdc8d8SChris Lattner bool stop_other_threads, 11830fdc8d8SChris Lattner bool discard_on_error) : 119b01e742aSJim Ingham ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion), 12030fdc8d8SChris Lattner m_valid (false), 1211ee0d4f7SBenjamin Kramer m_stop_other_threads (stop_other_threads), 12230fdc8d8SChris Lattner m_arg_addr (0), 12330fdc8d8SChris Lattner m_args (&args), 1241ee0d4f7SBenjamin Kramer m_process (thread.GetProcess()), 1251ee0d4f7SBenjamin Kramer m_thread (thread) 12630fdc8d8SChris Lattner { 12730fdc8d8SChris Lattner 12830fdc8d8SChris Lattner SetOkayToDiscard (discard_on_error); 12930fdc8d8SChris Lattner 13030fdc8d8SChris Lattner Process& process = thread.GetProcess(); 13130fdc8d8SChris Lattner Target& target = process.GetTarget(); 13230fdc8d8SChris Lattner const ABI *abi = process.GetABI(); 13330fdc8d8SChris Lattner 13430fdc8d8SChris Lattner if(!abi) 13530fdc8d8SChris Lattner return; 13630fdc8d8SChris Lattner 1376db73ca5SSean Callanan SetBreakpoints(); 1386db73ca5SSean Callanan 13930fdc8d8SChris Lattner lldb::addr_t spBelowRedZone = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize(); 14030fdc8d8SChris Lattner 14130fdc8d8SChris Lattner SymbolContextList contexts; 14230fdc8d8SChris Lattner SymbolContext context; 14330fdc8d8SChris Lattner ModuleSP executableModuleSP (target.GetExecutableModule()); 14430fdc8d8SChris Lattner 14530fdc8d8SChris Lattner if (!executableModuleSP || 14630fdc8d8SChris Lattner !executableModuleSP->FindSymbolsWithNameAndType(ConstString ("start"), eSymbolTypeCode, contexts)) 14730fdc8d8SChris Lattner return; 14830fdc8d8SChris Lattner 14930fdc8d8SChris Lattner contexts.GetContextAtIndex(0, context); 15030fdc8d8SChris Lattner 15130fdc8d8SChris Lattner m_start_addr = context.symbol->GetValue(); 152f5e56de0SGreg Clayton lldb::addr_t StartLoadAddr = m_start_addr.GetLoadAddress(&target); 15330fdc8d8SChris Lattner 15430fdc8d8SChris Lattner if(!thread.SaveFrameZeroState(m_register_backup)) 15530fdc8d8SChris Lattner return; 15630fdc8d8SChris Lattner 15730fdc8d8SChris Lattner m_function_addr = function; 158f5e56de0SGreg Clayton lldb::addr_t FunctionLoadAddr = m_function_addr.GetLoadAddress(&target); 15930fdc8d8SChris Lattner 16030fdc8d8SChris Lattner if (!abi->PrepareNormalCall(thread, 16130fdc8d8SChris Lattner spBelowRedZone, 16230fdc8d8SChris Lattner FunctionLoadAddr, 16330fdc8d8SChris Lattner StartLoadAddr, 16430fdc8d8SChris Lattner *m_args)) 16530fdc8d8SChris Lattner return; 16630fdc8d8SChris Lattner 167ece96492SSean Callanan LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 168ece96492SSean Callanan 169ece96492SSean Callanan if (log) 170ece96492SSean Callanan { 171ece96492SSean Callanan RegisterContext *reg_ctx = m_thread.GetRegisterContext(); 172ece96492SSean Callanan 173ece96492SSean Callanan log->PutCString("Function call was set up. Register state was:"); 174ece96492SSean Callanan 175ece96492SSean Callanan for (uint32_t register_index = 0, num_registers = reg_ctx->GetRegisterCount(); 176ece96492SSean Callanan register_index < num_registers; 177ece96492SSean Callanan ++register_index) 178ece96492SSean Callanan { 179ece96492SSean Callanan const char *register_name = reg_ctx->GetRegisterName(register_index); 180ece96492SSean Callanan uint64_t register_value = reg_ctx->ReadRegisterAsUnsigned(register_index, LLDB_INVALID_ADDRESS); 181ece96492SSean Callanan 182ece96492SSean Callanan log->Printf(" %s = 0x%llx", register_name, register_value); 183ece96492SSean Callanan } 184ece96492SSean Callanan } 185ece96492SSean Callanan 18630fdc8d8SChris Lattner m_valid = true; 18730fdc8d8SChris Lattner } 18830fdc8d8SChris Lattner 18930fdc8d8SChris Lattner ThreadPlanCallFunction::~ThreadPlanCallFunction () 19030fdc8d8SChris Lattner { 19110af7c43SSean Callanan if (m_valid && !IsPlanComplete()) 19210af7c43SSean Callanan DoTakedown(); 19310af7c43SSean Callanan } 19410af7c43SSean Callanan 19510af7c43SSean Callanan void 19610af7c43SSean Callanan ThreadPlanCallFunction::DoTakedown () 19710af7c43SSean Callanan { 19810af7c43SSean Callanan m_thread.RestoreSaveFrameZero(m_register_backup); 19910af7c43SSean Callanan m_thread.ClearStackFrames(); 20010af7c43SSean Callanan SetPlanComplete(); 20110af7c43SSean Callanan ClearBreakpoints(); 20230fdc8d8SChris Lattner } 20330fdc8d8SChris Lattner 20430fdc8d8SChris Lattner void 20530fdc8d8SChris Lattner ThreadPlanCallFunction::GetDescription (Stream *s, lldb::DescriptionLevel level) 20630fdc8d8SChris Lattner { 20730fdc8d8SChris Lattner if (level == lldb::eDescriptionLevelBrief) 20830fdc8d8SChris Lattner { 20930fdc8d8SChris Lattner s->Printf("Function call thread plan"); 21030fdc8d8SChris Lattner } 21130fdc8d8SChris Lattner else 21230fdc8d8SChris Lattner { 21330fdc8d8SChris Lattner if (m_args) 214f5e56de0SGreg Clayton s->Printf("Thread plan to call 0x%llx with parsed arguments", m_function_addr.GetLoadAddress(&m_process.GetTarget()), m_arg_addr); 21530fdc8d8SChris Lattner else 216f5e56de0SGreg Clayton s->Printf("Thread plan to call 0x%llx void * argument at: 0x%llx", m_function_addr.GetLoadAddress(&m_process.GetTarget()), m_arg_addr); 21730fdc8d8SChris Lattner } 21830fdc8d8SChris Lattner } 21930fdc8d8SChris Lattner 22030fdc8d8SChris Lattner bool 22130fdc8d8SChris Lattner ThreadPlanCallFunction::ValidatePlan (Stream *error) 22230fdc8d8SChris Lattner { 22330fdc8d8SChris Lattner if (!m_valid) 22430fdc8d8SChris Lattner return false; 22530fdc8d8SChris Lattner 22630fdc8d8SChris Lattner return true; 22730fdc8d8SChris Lattner } 22830fdc8d8SChris Lattner 22930fdc8d8SChris Lattner bool 23030fdc8d8SChris Lattner ThreadPlanCallFunction::PlanExplainsStop () 23130fdc8d8SChris Lattner { 23240d871faSJim Ingham // If our subplan knows why we stopped, even if it's done (which would forward the question to us) 23340d871faSJim Ingham // we answer yes. 23440d871faSJim Ingham if(m_subplan_sp.get() != NULL && m_subplan_sp->PlanExplainsStop()) 23540d871faSJim Ingham return true; 2363e6fedcaSSean Callanan 237c98aca60SSean Callanan // Check if the breakpoint is one of ours. 238c98aca60SSean Callanan 239c98aca60SSean Callanan if (BreakpointsExplainStop()) 240c98aca60SSean Callanan return true; 241c98aca60SSean Callanan 24240d871faSJim Ingham // If we don't want to discard this plan, than any stop we don't understand should be propagated up the stack. 24340d871faSJim Ingham if (!OkayToDiscard()) 24440d871faSJim Ingham return false; 24540d871faSJim Ingham 24640d871faSJim Ingham // Otherwise, check the case where we stopped for an internal breakpoint, in that case, continue on. 24740d871faSJim Ingham // If it is not an internal breakpoint, consult OkayToDiscard. 24840d871faSJim Ingham lldb::StopInfoSP stop_info_sp = GetPrivateStopReason(); 2496db73ca5SSean Callanan 25040d871faSJim Ingham if (stop_info_sp && stop_info_sp->GetStopReason() == eStopReasonBreakpoint) 25140d871faSJim Ingham { 25240d871faSJim Ingham uint64_t break_site_id = stop_info_sp->GetValue(); 25340d871faSJim Ingham lldb::BreakpointSiteSP bp_site_sp = m_thread.GetProcess().GetBreakpointSiteList().FindByID(break_site_id); 25440d871faSJim Ingham if (bp_site_sp) 25540d871faSJim Ingham { 25640d871faSJim Ingham uint32_t num_owners = bp_site_sp->GetNumberOfOwners(); 25740d871faSJim Ingham bool is_internal = true; 25840d871faSJim Ingham for (uint32_t i = 0; i < num_owners; i++) 25940d871faSJim Ingham { 2606db73ca5SSean Callanan Breakpoint &bp = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint(); 2616db73ca5SSean Callanan 2626db73ca5SSean Callanan if (!bp.IsInternal()) 26340d871faSJim Ingham { 26440d871faSJim Ingham is_internal = false; 26540d871faSJim Ingham break; 26640d871faSJim Ingham } 26740d871faSJim Ingham } 26840d871faSJim Ingham if (is_internal) 26940d871faSJim Ingham return false; 27040d871faSJim Ingham } 27140d871faSJim Ingham 27240d871faSJim Ingham return OkayToDiscard(); 27340d871faSJim Ingham } 27440d871faSJim Ingham else 27540d871faSJim Ingham { 27640d871faSJim Ingham // If the subplan is running, any crashes are attributable to us. 2773e6fedcaSSean Callanan return (m_subplan_sp.get() != NULL); 27830fdc8d8SChris Lattner } 27940d871faSJim Ingham } 28030fdc8d8SChris Lattner 28130fdc8d8SChris Lattner bool 28230fdc8d8SChris Lattner ThreadPlanCallFunction::ShouldStop (Event *event_ptr) 28330fdc8d8SChris Lattner { 28430fdc8d8SChris Lattner if (PlanExplainsStop()) 28530fdc8d8SChris Lattner { 2862d4edfbcSGreg Clayton LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 2875300d37aSSean Callanan 2885300d37aSSean Callanan if (log) 2895300d37aSSean Callanan { 2905300d37aSSean Callanan RegisterContext *reg_ctx = m_thread.GetRegisterContext(); 2915300d37aSSean Callanan 2925300d37aSSean Callanan log->PutCString("Function completed. Register state was:"); 2935300d37aSSean Callanan 2945300d37aSSean Callanan for (uint32_t register_index = 0, num_registers = reg_ctx->GetRegisterCount(); 2955300d37aSSean Callanan register_index < num_registers; 2965300d37aSSean Callanan ++register_index) 2975300d37aSSean Callanan { 2985300d37aSSean Callanan const char *register_name = reg_ctx->GetRegisterName(register_index); 2995300d37aSSean Callanan uint64_t register_value = reg_ctx->ReadRegisterAsUnsigned(register_index, LLDB_INVALID_ADDRESS); 3005300d37aSSean Callanan 3015300d37aSSean Callanan log->Printf(" %s = 0x%llx", register_name, register_value); 3025300d37aSSean Callanan } 3035300d37aSSean Callanan } 3045300d37aSSean Callanan 30510af7c43SSean Callanan DoTakedown(); 3066db73ca5SSean Callanan 30730fdc8d8SChris Lattner return true; 30830fdc8d8SChris Lattner } 30930fdc8d8SChris Lattner else 31030fdc8d8SChris Lattner { 31130fdc8d8SChris Lattner return false; 31230fdc8d8SChris Lattner } 31330fdc8d8SChris Lattner } 31430fdc8d8SChris Lattner 31530fdc8d8SChris Lattner bool 31630fdc8d8SChris Lattner ThreadPlanCallFunction::StopOthers () 31730fdc8d8SChris Lattner { 31830fdc8d8SChris Lattner return m_stop_other_threads; 31930fdc8d8SChris Lattner } 32030fdc8d8SChris Lattner 32130fdc8d8SChris Lattner void 32230fdc8d8SChris Lattner ThreadPlanCallFunction::SetStopOthers (bool new_value) 32330fdc8d8SChris Lattner { 32430fdc8d8SChris Lattner if (m_subplan_sp) 32530fdc8d8SChris Lattner { 32630fdc8d8SChris Lattner ThreadPlanRunToAddress *address_plan = static_cast<ThreadPlanRunToAddress *>(m_subplan_sp.get()); 32730fdc8d8SChris Lattner address_plan->SetStopOthers(new_value); 32830fdc8d8SChris Lattner } 32930fdc8d8SChris Lattner m_stop_other_threads = new_value; 33030fdc8d8SChris Lattner } 33130fdc8d8SChris Lattner 33230fdc8d8SChris Lattner StateType 333*06e827ccSJim Ingham ThreadPlanCallFunction::GetPlanRunState () 33430fdc8d8SChris Lattner { 33530fdc8d8SChris Lattner return eStateRunning; 33630fdc8d8SChris Lattner } 33730fdc8d8SChris Lattner 33830fdc8d8SChris Lattner void 33930fdc8d8SChris Lattner ThreadPlanCallFunction::DidPush () 34030fdc8d8SChris Lattner { 341be3a1b14SSean Callanan //#define SINGLE_STEP_EXPRESSIONS 342be3a1b14SSean Callanan 343be3a1b14SSean Callanan #ifndef SINGLE_STEP_EXPRESSIONS 34430fdc8d8SChris Lattner m_subplan_sp.reset(new ThreadPlanRunToAddress(m_thread, m_start_addr, m_stop_other_threads)); 34530fdc8d8SChris Lattner 34630fdc8d8SChris Lattner m_thread.QueueThreadPlan(m_subplan_sp, false); 347be3a1b14SSean Callanan #endif 34830fdc8d8SChris Lattner } 34930fdc8d8SChris Lattner 35030fdc8d8SChris Lattner bool 35130fdc8d8SChris Lattner ThreadPlanCallFunction::WillStop () 35230fdc8d8SChris Lattner { 35330fdc8d8SChris Lattner return true; 35430fdc8d8SChris Lattner } 35530fdc8d8SChris Lattner 35630fdc8d8SChris Lattner bool 35730fdc8d8SChris Lattner ThreadPlanCallFunction::MischiefManaged () 35830fdc8d8SChris Lattner { 35930fdc8d8SChris Lattner if (IsPlanComplete()) 36030fdc8d8SChris Lattner { 3612d4edfbcSGreg Clayton LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 36230fdc8d8SChris Lattner 36330fdc8d8SChris Lattner if (log) 36430fdc8d8SChris Lattner log->Printf("Completed call function plan."); 36530fdc8d8SChris Lattner 36630fdc8d8SChris Lattner ThreadPlan::MischiefManaged (); 36730fdc8d8SChris Lattner return true; 36830fdc8d8SChris Lattner } 36930fdc8d8SChris Lattner else 37030fdc8d8SChris Lattner { 37130fdc8d8SChris Lattner return false; 37230fdc8d8SChris Lattner } 37330fdc8d8SChris Lattner } 3746db73ca5SSean Callanan 3756db73ca5SSean Callanan void 3766db73ca5SSean Callanan ThreadPlanCallFunction::SetBreakpoints () 3776db73ca5SSean Callanan { 378f211510fSSean Callanan m_cxx_language_runtime = m_process.GetLanguageRuntime(eLanguageTypeC_plus_plus); 379f211510fSSean Callanan m_objc_language_runtime = m_process.GetLanguageRuntime(eLanguageTypeObjC); 3806db73ca5SSean Callanan 381f211510fSSean Callanan if (m_cxx_language_runtime) 382f211510fSSean Callanan m_cxx_language_runtime->SetExceptionBreakpoints(); 383f211510fSSean Callanan if (m_objc_language_runtime) 384f211510fSSean Callanan m_objc_language_runtime->SetExceptionBreakpoints(); 3856db73ca5SSean Callanan } 3866db73ca5SSean Callanan 3876db73ca5SSean Callanan void 3886db73ca5SSean Callanan ThreadPlanCallFunction::ClearBreakpoints () 3896db73ca5SSean Callanan { 390f211510fSSean Callanan if (m_cxx_language_runtime) 391f211510fSSean Callanan m_cxx_language_runtime->ClearExceptionBreakpoints(); 392f211510fSSean Callanan if (m_objc_language_runtime) 393f211510fSSean Callanan m_objc_language_runtime->ClearExceptionBreakpoints(); 3946db73ca5SSean Callanan } 395c98aca60SSean Callanan 396c98aca60SSean Callanan bool 397c98aca60SSean Callanan ThreadPlanCallFunction::BreakpointsExplainStop() 398c98aca60SSean Callanan { 399c98aca60SSean Callanan lldb::StopInfoSP stop_info_sp = GetPrivateStopReason(); 400c98aca60SSean Callanan 401f211510fSSean Callanan if (m_cxx_language_runtime && 402f211510fSSean Callanan m_cxx_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp)) 403c98aca60SSean Callanan return true; 404f211510fSSean Callanan 405f211510fSSean Callanan if (m_objc_language_runtime && 406f211510fSSean Callanan m_objc_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp)) 407f211510fSSean Callanan return true; 408c98aca60SSean Callanan 409c98aca60SSean Callanan return false; 410c98aca60SSean Callanan } 411