1ac7ddfbfSEd Maste //===-- ThreadPlanCallFunction.cpp ------------------------------*- C++ -*-===// 2ac7ddfbfSEd Maste // 3ac7ddfbfSEd Maste // The LLVM Compiler Infrastructure 4ac7ddfbfSEd Maste // 5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source 6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details. 7ac7ddfbfSEd Maste // 8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===// 9ac7ddfbfSEd Maste 10ac7ddfbfSEd Maste // C Includes 11ac7ddfbfSEd Maste // C++ Includes 12ac7ddfbfSEd Maste // Other libraries and framework includes 13ac7ddfbfSEd Maste // Project includes 149f2f44ceSEd Maste #include "lldb/Target/ThreadPlanCallFunction.h" 15ac7ddfbfSEd Maste #include "lldb/Breakpoint/Breakpoint.h" 16ac7ddfbfSEd Maste #include "lldb/Breakpoint/BreakpointLocation.h" 17ac7ddfbfSEd Maste #include "lldb/Core/Address.h" 18ac7ddfbfSEd Maste #include "lldb/Core/Log.h" 19ac7ddfbfSEd Maste #include "lldb/Core/Module.h" 20ac7ddfbfSEd Maste #include "lldb/Core/Stream.h" 21ac7ddfbfSEd Maste #include "lldb/Symbol/ObjectFile.h" 221c3bbb01SEd Maste #include "lldb/Target/ABI.h" 23ac7ddfbfSEd Maste #include "lldb/Target/LanguageRuntime.h" 24ac7ddfbfSEd Maste #include "lldb/Target/Process.h" 25ac7ddfbfSEd Maste #include "lldb/Target/RegisterContext.h" 26ac7ddfbfSEd Maste #include "lldb/Target/StopInfo.h" 27ac7ddfbfSEd Maste #include "lldb/Target/Target.h" 28ac7ddfbfSEd Maste #include "lldb/Target/Thread.h" 29ac7ddfbfSEd Maste #include "lldb/Target/ThreadPlanRunToAddress.h" 30ac7ddfbfSEd Maste 31ac7ddfbfSEd Maste using namespace lldb; 32ac7ddfbfSEd Maste using namespace lldb_private; 33ac7ddfbfSEd Maste 34ac7ddfbfSEd Maste //---------------------------------------------------------------------- 35ac7ddfbfSEd Maste // ThreadPlanCallFunction: Plan to call a single function 36ac7ddfbfSEd Maste //---------------------------------------------------------------------- 37435933ddSDimitry Andric bool ThreadPlanCallFunction::ConstructorSetup( 38435933ddSDimitry Andric Thread &thread, ABI *&abi, lldb::addr_t &start_load_addr, 39435933ddSDimitry Andric lldb::addr_t &function_load_addr) { 40ac7ddfbfSEd Maste SetIsMasterPlan(true); 41ac7ddfbfSEd Maste SetOkayToDiscard(false); 42ac7ddfbfSEd Maste SetPrivate(true); 43ac7ddfbfSEd Maste 44ac7ddfbfSEd Maste ProcessSP process_sp(thread.GetProcess()); 45ac7ddfbfSEd Maste if (!process_sp) 46ac7ddfbfSEd Maste return false; 47ac7ddfbfSEd Maste 48ac7ddfbfSEd Maste abi = process_sp->GetABI().get(); 49ac7ddfbfSEd Maste 50ac7ddfbfSEd Maste if (!abi) 51ac7ddfbfSEd Maste return false; 52ac7ddfbfSEd Maste 53ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_STEP)); 54ac7ddfbfSEd Maste 55ac7ddfbfSEd Maste SetBreakpoints(); 56ac7ddfbfSEd Maste 57ac7ddfbfSEd Maste m_function_sp = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize(); 58435933ddSDimitry Andric // If we can't read memory at the point of the process where we are planning 59435933ddSDimitry Andric // to put our function, we're 60ac7ddfbfSEd Maste // not going to get any further... 61ac7ddfbfSEd Maste Error error; 62ac7ddfbfSEd Maste process_sp->ReadUnsignedIntegerFromMemory(m_function_sp, 4, 0, error); 63435933ddSDimitry Andric if (!error.Success()) { 64435933ddSDimitry Andric m_constructor_errors.Printf( 65435933ddSDimitry Andric "Trying to put the stack in unreadable memory at: 0x%" PRIx64 ".", 66435933ddSDimitry Andric m_function_sp); 67ac7ddfbfSEd Maste if (log) 68435933ddSDimitry Andric log->Printf("ThreadPlanCallFunction(%p): %s.", static_cast<void *>(this), 690127ef0fSEd Maste m_constructor_errors.GetData()); 70ac7ddfbfSEd Maste return false; 71ac7ddfbfSEd Maste } 72ac7ddfbfSEd Maste 73b952cd58SEd Maste Module *exe_module = GetTarget().GetExecutableModulePointer(); 74ac7ddfbfSEd Maste 75435933ddSDimitry Andric if (exe_module == nullptr) { 76435933ddSDimitry Andric m_constructor_errors.Printf( 77435933ddSDimitry Andric "Can't execute code without an executable module."); 78ac7ddfbfSEd Maste if (log) 79435933ddSDimitry Andric log->Printf("ThreadPlanCallFunction(%p): %s.", static_cast<void *>(this), 800127ef0fSEd Maste m_constructor_errors.GetData()); 81ac7ddfbfSEd Maste return false; 82435933ddSDimitry Andric } else { 83ac7ddfbfSEd Maste ObjectFile *objectFile = exe_module->GetObjectFile(); 84435933ddSDimitry Andric if (!objectFile) { 85435933ddSDimitry Andric m_constructor_errors.Printf( 86435933ddSDimitry Andric "Could not find object file for module \"%s\".", 87ac7ddfbfSEd Maste exe_module->GetFileSpec().GetFilename().AsCString()); 88ac7ddfbfSEd Maste 89ac7ddfbfSEd Maste if (log) 900127ef0fSEd Maste log->Printf("ThreadPlanCallFunction(%p): %s.", 91435933ddSDimitry Andric static_cast<void *>(this), m_constructor_errors.GetData()); 92ac7ddfbfSEd Maste return false; 93ac7ddfbfSEd Maste } 94ac7ddfbfSEd Maste 95ac7ddfbfSEd Maste m_start_addr = objectFile->GetEntryPointAddress(); 96435933ddSDimitry Andric if (!m_start_addr.IsValid()) { 97435933ddSDimitry Andric m_constructor_errors.Printf( 98435933ddSDimitry Andric "Could not find entry point address for executable module \"%s\".", 99ac7ddfbfSEd Maste exe_module->GetFileSpec().GetFilename().AsCString()); 100ac7ddfbfSEd Maste if (log) 1010127ef0fSEd Maste log->Printf("ThreadPlanCallFunction(%p): %s.", 102435933ddSDimitry Andric static_cast<void *>(this), m_constructor_errors.GetData()); 103ac7ddfbfSEd Maste return false; 104ac7ddfbfSEd Maste } 105ac7ddfbfSEd Maste } 106ac7ddfbfSEd Maste 107b952cd58SEd Maste start_load_addr = m_start_addr.GetLoadAddress(&GetTarget()); 108ac7ddfbfSEd Maste 109ac7ddfbfSEd Maste // Checkpoint the thread state so we can restore it later. 110ac7ddfbfSEd Maste if (log && log->GetVerbose()) 111435933ddSDimitry Andric ReportRegisterState("About to checkpoint thread before function call. " 112435933ddSDimitry Andric "Original register state was:"); 113ac7ddfbfSEd Maste 114435933ddSDimitry Andric if (!thread.CheckpointThreadState(m_stored_thread_state)) { 115435933ddSDimitry Andric m_constructor_errors.Printf("Setting up ThreadPlanCallFunction, failed to " 116435933ddSDimitry Andric "checkpoint thread state."); 117ac7ddfbfSEd Maste if (log) 118435933ddSDimitry Andric log->Printf("ThreadPlanCallFunction(%p): %s.", static_cast<void *>(this), 1190127ef0fSEd Maste m_constructor_errors.GetData()); 120ac7ddfbfSEd Maste return false; 121ac7ddfbfSEd Maste } 122b952cd58SEd Maste function_load_addr = m_function_addr.GetLoadAddress(&GetTarget()); 123ac7ddfbfSEd Maste 124ac7ddfbfSEd Maste return true; 125ac7ddfbfSEd Maste } 126ac7ddfbfSEd Maste 127435933ddSDimitry Andric ThreadPlanCallFunction::ThreadPlanCallFunction( 128435933ddSDimitry Andric Thread &thread, const Address &function, const CompilerType &return_type, 129435933ddSDimitry Andric llvm::ArrayRef<addr_t> args, const EvaluateExpressionOptions &options) 130435933ddSDimitry Andric : ThreadPlan(ThreadPlan::eKindCallFunction, "Call function plan", thread, 131435933ddSDimitry Andric eVoteNoOpinion, eVoteNoOpinion), 132435933ddSDimitry Andric m_valid(false), m_stop_other_threads(options.GetStopOthers()), 133b952cd58SEd Maste m_unwind_on_error(options.DoesUnwindOnError()), 134b952cd58SEd Maste m_ignore_breakpoints(options.DoesIgnoreBreakpoints()), 135b952cd58SEd Maste m_debug_execution(options.GetDebug()), 136435933ddSDimitry Andric m_trap_exceptions(options.GetTrapExceptions()), m_function_addr(function), 137435933ddSDimitry Andric m_function_sp(0), m_takedown_done(false), 138b952cd58SEd Maste m_should_clear_objc_exception_bp(false), 139b952cd58SEd Maste m_should_clear_cxx_exception_bp(false), 140435933ddSDimitry Andric m_stop_address(LLDB_INVALID_ADDRESS), m_return_type(return_type) { 141b91a7dfcSDimitry Andric lldb::addr_t start_load_addr = LLDB_INVALID_ADDRESS; 142b91a7dfcSDimitry Andric lldb::addr_t function_load_addr = LLDB_INVALID_ADDRESS; 143b91a7dfcSDimitry Andric ABI *abi = nullptr; 144b91a7dfcSDimitry Andric 145ac7ddfbfSEd Maste if (!ConstructorSetup(thread, abi, start_load_addr, function_load_addr)) 146ac7ddfbfSEd Maste return; 147ac7ddfbfSEd Maste 148435933ddSDimitry Andric if (!abi->PrepareTrivialCall(thread, m_function_sp, function_load_addr, 149435933ddSDimitry Andric start_load_addr, args)) 150ac7ddfbfSEd Maste return; 151ac7ddfbfSEd Maste 152ac7ddfbfSEd Maste ReportRegisterState("Function call was set up. Register state was:"); 153ac7ddfbfSEd Maste 154ac7ddfbfSEd Maste m_valid = true; 155ac7ddfbfSEd Maste } 156ac7ddfbfSEd Maste 157435933ddSDimitry Andric ThreadPlanCallFunction::ThreadPlanCallFunction( 158435933ddSDimitry Andric Thread &thread, const Address &function, 159435933ddSDimitry Andric const EvaluateExpressionOptions &options) 160435933ddSDimitry Andric : ThreadPlan(ThreadPlan::eKindCallFunction, "Call function plan", thread, 161435933ddSDimitry Andric eVoteNoOpinion, eVoteNoOpinion), 162435933ddSDimitry Andric m_valid(false), m_stop_other_threads(options.GetStopOthers()), 163b91a7dfcSDimitry Andric m_unwind_on_error(options.DoesUnwindOnError()), 164b91a7dfcSDimitry Andric m_ignore_breakpoints(options.DoesIgnoreBreakpoints()), 165b91a7dfcSDimitry Andric m_debug_execution(options.GetDebug()), 166435933ddSDimitry Andric m_trap_exceptions(options.GetTrapExceptions()), m_function_addr(function), 167435933ddSDimitry Andric m_function_sp(0), m_takedown_done(false), 168b91a7dfcSDimitry Andric m_should_clear_objc_exception_bp(false), 169b91a7dfcSDimitry Andric m_should_clear_cxx_exception_bp(false), 170435933ddSDimitry Andric m_stop_address(LLDB_INVALID_ADDRESS), m_return_type(CompilerType()) {} 171b91a7dfcSDimitry Andric 172435933ddSDimitry Andric ThreadPlanCallFunction::~ThreadPlanCallFunction() { 173ac7ddfbfSEd Maste DoTakedown(PlanSucceeded()); 174ac7ddfbfSEd Maste } 175ac7ddfbfSEd Maste 176435933ddSDimitry Andric void ThreadPlanCallFunction::ReportRegisterState(const char *message) { 177435933ddSDimitry Andric Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP | 178435933ddSDimitry Andric LIBLLDB_LOG_VERBOSE)); 179435933ddSDimitry Andric if (log) { 180ac7ddfbfSEd Maste StreamString strm; 181ac7ddfbfSEd Maste RegisterContext *reg_ctx = m_thread.GetRegisterContext().get(); 182ac7ddfbfSEd Maste 183ac7ddfbfSEd Maste log->PutCString(message); 184ac7ddfbfSEd Maste 185ac7ddfbfSEd Maste RegisterValue reg_value; 186ac7ddfbfSEd Maste 187ac7ddfbfSEd Maste for (uint32_t reg_idx = 0, num_registers = reg_ctx->GetRegisterCount(); 188435933ddSDimitry Andric reg_idx < num_registers; ++reg_idx) { 189ac7ddfbfSEd Maste const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_idx); 190435933ddSDimitry Andric if (reg_ctx->ReadRegister(reg_info, reg_value)) { 191ac7ddfbfSEd Maste reg_value.Dump(&strm, reg_info, true, false, eFormatDefault); 192ac7ddfbfSEd Maste strm.EOL(); 193ac7ddfbfSEd Maste } 194ac7ddfbfSEd Maste } 195435933ddSDimitry Andric log->PutString(strm.GetString()); 196ac7ddfbfSEd Maste } 197ac7ddfbfSEd Maste } 198ac7ddfbfSEd Maste 199435933ddSDimitry Andric void ThreadPlanCallFunction::DoTakedown(bool success) { 200ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_STEP)); 201ac7ddfbfSEd Maste 202435933ddSDimitry Andric if (!m_valid) { 203ac7ddfbfSEd Maste // Don't call DoTakedown if we were never valid to begin with. 204ac7ddfbfSEd Maste if (log) 205435933ddSDimitry Andric log->Printf("ThreadPlanCallFunction(%p): Log called on " 206435933ddSDimitry Andric "ThreadPlanCallFunction that was never valid.", 2070127ef0fSEd Maste static_cast<void *>(this)); 208ac7ddfbfSEd Maste return; 209ac7ddfbfSEd Maste } 210ac7ddfbfSEd Maste 211435933ddSDimitry Andric if (!m_takedown_done) { 212435933ddSDimitry Andric if (success) { 213b91a7dfcSDimitry Andric SetReturnValue(); 214ac7ddfbfSEd Maste } 215ac7ddfbfSEd Maste if (log) 216435933ddSDimitry Andric log->Printf("ThreadPlanCallFunction(%p): DoTakedown called for thread " 217435933ddSDimitry Andric "0x%4.4" PRIx64 ", m_valid: %d complete: %d.\n", 2180127ef0fSEd Maste static_cast<void *>(this), m_thread.GetID(), m_valid, 2190127ef0fSEd Maste IsPlanComplete()); 220ac7ddfbfSEd Maste m_takedown_done = true; 221435933ddSDimitry Andric m_stop_address = 222435933ddSDimitry Andric m_thread.GetStackFrameAtIndex(0)->GetRegisterContext()->GetPC(); 223ac7ddfbfSEd Maste m_real_stop_info_sp = GetPrivateStopInfo(); 224435933ddSDimitry Andric if (!m_thread.RestoreRegisterStateFromCheckpoint(m_stored_thread_state)) { 225*afda932aSEd Maste if (log) 226435933ddSDimitry Andric log->Printf("ThreadPlanCallFunction(%p): DoTakedown failed to restore " 227435933ddSDimitry Andric "register state", 2280127ef0fSEd Maste static_cast<void *>(this)); 229*afda932aSEd Maste } 230ac7ddfbfSEd Maste SetPlanComplete(success); 231ac7ddfbfSEd Maste ClearBreakpoints(); 232ac7ddfbfSEd Maste if (log && log->GetVerbose()) 233435933ddSDimitry Andric ReportRegisterState("Restoring thread state after function call. " 234435933ddSDimitry Andric "Restored register state:"); 235435933ddSDimitry Andric } else { 236ac7ddfbfSEd Maste if (log) 237435933ddSDimitry Andric log->Printf("ThreadPlanCallFunction(%p): DoTakedown called as no-op for " 238435933ddSDimitry Andric "thread 0x%4.4" PRIx64 ", m_valid: %d complete: %d.\n", 2390127ef0fSEd Maste static_cast<void *>(this), m_thread.GetID(), m_valid, 2400127ef0fSEd Maste IsPlanComplete()); 241ac7ddfbfSEd Maste } 242ac7ddfbfSEd Maste } 243ac7ddfbfSEd Maste 244435933ddSDimitry Andric void ThreadPlanCallFunction::WillPop() { DoTakedown(PlanSucceeded()); } 245ac7ddfbfSEd Maste 246435933ddSDimitry Andric void ThreadPlanCallFunction::GetDescription(Stream *s, DescriptionLevel level) { 247435933ddSDimitry Andric if (level == eDescriptionLevelBrief) { 248ac7ddfbfSEd Maste s->Printf("Function call thread plan"); 249435933ddSDimitry Andric } else { 250ac7ddfbfSEd Maste TargetSP target_sp(m_thread.CalculateTarget()); 251435933ddSDimitry Andric s->Printf("Thread plan to call 0x%" PRIx64, 252435933ddSDimitry Andric m_function_addr.GetLoadAddress(target_sp.get())); 253ac7ddfbfSEd Maste } 254ac7ddfbfSEd Maste } 255ac7ddfbfSEd Maste 256435933ddSDimitry Andric bool ThreadPlanCallFunction::ValidatePlan(Stream *error) { 257435933ddSDimitry Andric if (!m_valid) { 258435933ddSDimitry Andric if (error) { 259ac7ddfbfSEd Maste if (m_constructor_errors.GetSize() > 0) 260435933ddSDimitry Andric error->PutCString(m_constructor_errors.GetString()); 261ac7ddfbfSEd Maste else 262ac7ddfbfSEd Maste error->PutCString("Unknown error"); 263ac7ddfbfSEd Maste } 264ac7ddfbfSEd Maste return false; 265ac7ddfbfSEd Maste } 266ac7ddfbfSEd Maste 267ac7ddfbfSEd Maste return true; 268ac7ddfbfSEd Maste } 269ac7ddfbfSEd Maste 270435933ddSDimitry Andric Vote ThreadPlanCallFunction::ShouldReportStop(Event *event_ptr) { 271ac7ddfbfSEd Maste if (m_takedown_done || IsPlanComplete()) 272ac7ddfbfSEd Maste return eVoteYes; 273ac7ddfbfSEd Maste else 274ac7ddfbfSEd Maste return ThreadPlan::ShouldReportStop(event_ptr); 275ac7ddfbfSEd Maste } 276ac7ddfbfSEd Maste 277435933ddSDimitry Andric bool ThreadPlanCallFunction::DoPlanExplainsStop(Event *event_ptr) { 278435933ddSDimitry Andric Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_STEP | 279435933ddSDimitry Andric LIBLLDB_LOG_PROCESS)); 280ac7ddfbfSEd Maste m_real_stop_info_sp = GetPrivateStopInfo(); 281ac7ddfbfSEd Maste 282435933ddSDimitry Andric // If our subplan knows why we stopped, even if it's done (which would forward 283435933ddSDimitry Andric // the question to us) 284ac7ddfbfSEd Maste // we answer yes. 285435933ddSDimitry Andric if (m_subplan_sp && m_subplan_sp->PlanExplainsStop(event_ptr)) { 286ac7ddfbfSEd Maste SetPlanComplete(); 287ac7ddfbfSEd Maste return true; 288ac7ddfbfSEd Maste } 289ac7ddfbfSEd Maste 290ac7ddfbfSEd Maste // Check if the breakpoint is one of ours. 291ac7ddfbfSEd Maste 292ac7ddfbfSEd Maste StopReason stop_reason; 293ac7ddfbfSEd Maste if (!m_real_stop_info_sp) 294ac7ddfbfSEd Maste stop_reason = eStopReasonNone; 295ac7ddfbfSEd Maste else 296ac7ddfbfSEd Maste stop_reason = m_real_stop_info_sp->GetStopReason(); 297ac7ddfbfSEd Maste if (log) 298435933ddSDimitry Andric log->Printf( 299435933ddSDimitry Andric "ThreadPlanCallFunction::PlanExplainsStop: Got stop reason - %s.", 300435933ddSDimitry Andric Thread::StopReasonAsCString(stop_reason)); 301ac7ddfbfSEd Maste 302ac7ddfbfSEd Maste if (stop_reason == eStopReasonBreakpoint && BreakpointsExplainStop()) 303ac7ddfbfSEd Maste return true; 304ac7ddfbfSEd Maste 305435933ddSDimitry Andric // One more quirk here. If this event was from Halt interrupting the target, 306435933ddSDimitry Andric // then we should not consider 3070127ef0fSEd Maste // ourselves complete. Return true to acknowledge the stop. 308435933ddSDimitry Andric if (Process::ProcessEventData::GetInterruptedFromEvent(event_ptr)) { 3090127ef0fSEd Maste if (log) 310435933ddSDimitry Andric log->Printf("ThreadPlanCallFunction::PlanExplainsStop: The event is an " 311435933ddSDimitry Andric "Interrupt, returning true."); 3120127ef0fSEd Maste return true; 3130127ef0fSEd Maste } 314ac7ddfbfSEd Maste // We control breakpoints separately from other "stop reasons." So first, 315435933ddSDimitry Andric // check the case where we stopped for an internal breakpoint, in that case, 316435933ddSDimitry Andric // continue on. 317ac7ddfbfSEd Maste // If it is not an internal breakpoint, consult m_ignore_breakpoints. 318ac7ddfbfSEd Maste 319435933ddSDimitry Andric if (stop_reason == eStopReasonBreakpoint) { 320ac7ddfbfSEd Maste ProcessSP process_sp(m_thread.CalculateProcess()); 321ac7ddfbfSEd Maste uint64_t break_site_id = m_real_stop_info_sp->GetValue(); 322ac7ddfbfSEd Maste BreakpointSiteSP bp_site_sp; 323ac7ddfbfSEd Maste if (process_sp) 324ac7ddfbfSEd Maste bp_site_sp = process_sp->GetBreakpointSiteList().FindByID(break_site_id); 325435933ddSDimitry Andric if (bp_site_sp) { 326ac7ddfbfSEd Maste uint32_t num_owners = bp_site_sp->GetNumberOfOwners(); 327ac7ddfbfSEd Maste bool is_internal = true; 328435933ddSDimitry Andric for (uint32_t i = 0; i < num_owners; i++) { 329ac7ddfbfSEd Maste Breakpoint &bp = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint(); 330ac7ddfbfSEd Maste if (log) 331435933ddSDimitry Andric log->Printf("ThreadPlanCallFunction::PlanExplainsStop: hit " 332435933ddSDimitry Andric "breakpoint %d while calling function", 333435933ddSDimitry Andric bp.GetID()); 334ac7ddfbfSEd Maste 335435933ddSDimitry Andric if (!bp.IsInternal()) { 336ac7ddfbfSEd Maste is_internal = false; 337ac7ddfbfSEd Maste break; 338ac7ddfbfSEd Maste } 339ac7ddfbfSEd Maste } 340435933ddSDimitry Andric if (is_internal) { 341ac7ddfbfSEd Maste if (log) 342435933ddSDimitry Andric log->Printf("ThreadPlanCallFunction::PlanExplainsStop hit an " 343435933ddSDimitry Andric "internal breakpoint, not stopping."); 344ac7ddfbfSEd Maste return false; 345ac7ddfbfSEd Maste } 346ac7ddfbfSEd Maste } 347ac7ddfbfSEd Maste 348435933ddSDimitry Andric if (m_ignore_breakpoints) { 349ac7ddfbfSEd Maste if (log) 350435933ddSDimitry Andric log->Printf("ThreadPlanCallFunction::PlanExplainsStop: we are ignoring " 351435933ddSDimitry Andric "breakpoints, overriding breakpoint stop info ShouldStop, " 352435933ddSDimitry Andric "returning true"); 353ac7ddfbfSEd Maste m_real_stop_info_sp->OverrideShouldStop(false); 354ac7ddfbfSEd Maste return true; 355435933ddSDimitry Andric } else { 356ac7ddfbfSEd Maste if (log) 357435933ddSDimitry Andric log->Printf("ThreadPlanCallFunction::PlanExplainsStop: we are not " 358435933ddSDimitry Andric "ignoring breakpoints, overriding breakpoint stop info " 359435933ddSDimitry Andric "ShouldStop, returning true"); 360ac7ddfbfSEd Maste m_real_stop_info_sp->OverrideShouldStop(true); 361ac7ddfbfSEd Maste return false; 362ac7ddfbfSEd Maste } 363435933ddSDimitry Andric } else if (!m_unwind_on_error) { 364435933ddSDimitry Andric // If we don't want to discard this plan, than any stop we don't understand 365435933ddSDimitry Andric // should be propagated up the stack. 366ac7ddfbfSEd Maste return false; 367435933ddSDimitry Andric } else { 368ac7ddfbfSEd Maste // If the subplan is running, any crashes are attributable to us. 369ac7ddfbfSEd Maste // If we want to discard the plan, then we say we explain the stop 370ac7ddfbfSEd Maste // but if we are going to be discarded, let whoever is above us 371ac7ddfbfSEd Maste // explain the stop. 372435933ddSDimitry Andric // But don't discard the plan if the stop would restart itself (for instance 373435933ddSDimitry Andric // if it is a 374435933ddSDimitry Andric // signal that is set not to stop. Check that here first. We just say we 375435933ddSDimitry Andric // explain the stop 376ac7ddfbfSEd Maste // but aren't done and everything will continue on from there. 377ac7ddfbfSEd Maste 378435933ddSDimitry Andric if (m_real_stop_info_sp && 379435933ddSDimitry Andric m_real_stop_info_sp->ShouldStopSynchronous(event_ptr)) { 380ac7ddfbfSEd Maste SetPlanComplete(false); 3819f2f44ceSEd Maste return m_subplan_sp ? m_unwind_on_error : false; 382435933ddSDimitry Andric } else 383ac7ddfbfSEd Maste return true; 384ac7ddfbfSEd Maste } 385ac7ddfbfSEd Maste } 386ac7ddfbfSEd Maste 387435933ddSDimitry Andric bool ThreadPlanCallFunction::ShouldStop(Event *event_ptr) { 388435933ddSDimitry Andric // We do some computation in DoPlanExplainsStop that may or may not set the 389435933ddSDimitry Andric // plan as complete. 390ac7ddfbfSEd Maste // We need to do that here to make sure our state is correct. 391ac7ddfbfSEd Maste DoPlanExplainsStop(event_ptr); 392ac7ddfbfSEd Maste 393435933ddSDimitry Andric if (IsPlanComplete()) { 394ac7ddfbfSEd Maste ReportRegisterState("Function completed. Register state was:"); 395ac7ddfbfSEd Maste return true; 396435933ddSDimitry Andric } else { 397ac7ddfbfSEd Maste return false; 398ac7ddfbfSEd Maste } 399ac7ddfbfSEd Maste } 400ac7ddfbfSEd Maste 401435933ddSDimitry Andric bool ThreadPlanCallFunction::StopOthers() { return m_stop_other_threads; } 402ac7ddfbfSEd Maste 403435933ddSDimitry Andric StateType ThreadPlanCallFunction::GetPlanRunState() { return eStateRunning; } 404ac7ddfbfSEd Maste 405435933ddSDimitry Andric void ThreadPlanCallFunction::DidPush() { 406ac7ddfbfSEd Maste //#define SINGLE_STEP_EXPRESSIONS 407ac7ddfbfSEd Maste 408435933ddSDimitry Andric // Now set the thread state to "no reason" so we don't run with whatever 409435933ddSDimitry Andric // signal was outstanding... 410435933ddSDimitry Andric // Wait till the plan is pushed so we aren't changing the stop info till we're 411435933ddSDimitry Andric // about to run. 412ac7ddfbfSEd Maste 413ac7ddfbfSEd Maste GetThread().SetStopInfoToNothing(); 414ac7ddfbfSEd Maste 415ac7ddfbfSEd Maste #ifndef SINGLE_STEP_EXPRESSIONS 416435933ddSDimitry Andric m_subplan_sp.reset( 417435933ddSDimitry Andric new ThreadPlanRunToAddress(m_thread, m_start_addr, m_stop_other_threads)); 418ac7ddfbfSEd Maste 419ac7ddfbfSEd Maste m_thread.QueueThreadPlan(m_subplan_sp, false); 420ac7ddfbfSEd Maste m_subplan_sp->SetPrivate(true); 421ac7ddfbfSEd Maste #endif 422ac7ddfbfSEd Maste } 423ac7ddfbfSEd Maste 424435933ddSDimitry Andric bool ThreadPlanCallFunction::WillStop() { return true; } 425ac7ddfbfSEd Maste 426435933ddSDimitry Andric bool ThreadPlanCallFunction::MischiefManaged() { 427ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); 428ac7ddfbfSEd Maste 429435933ddSDimitry Andric if (IsPlanComplete()) { 430ac7ddfbfSEd Maste if (log) 4310127ef0fSEd Maste log->Printf("ThreadPlanCallFunction(%p): Completed call function plan.", 4320127ef0fSEd Maste static_cast<void *>(this)); 433ac7ddfbfSEd Maste 434ac7ddfbfSEd Maste ThreadPlan::MischiefManaged(); 435ac7ddfbfSEd Maste return true; 436435933ddSDimitry Andric } else { 437ac7ddfbfSEd Maste return false; 438ac7ddfbfSEd Maste } 439ac7ddfbfSEd Maste } 440ac7ddfbfSEd Maste 441435933ddSDimitry Andric void ThreadPlanCallFunction::SetBreakpoints() { 442ac7ddfbfSEd Maste ProcessSP process_sp(m_thread.CalculateProcess()); 443435933ddSDimitry Andric if (m_trap_exceptions && process_sp) { 444435933ddSDimitry Andric m_cxx_language_runtime = 445435933ddSDimitry Andric process_sp->GetLanguageRuntime(eLanguageTypeC_plus_plus); 446ac7ddfbfSEd Maste m_objc_language_runtime = process_sp->GetLanguageRuntime(eLanguageTypeObjC); 447ac7ddfbfSEd Maste 448435933ddSDimitry Andric if (m_cxx_language_runtime) { 449435933ddSDimitry Andric m_should_clear_cxx_exception_bp = 450435933ddSDimitry Andric !m_cxx_language_runtime->ExceptionBreakpointsAreSet(); 451ac7ddfbfSEd Maste m_cxx_language_runtime->SetExceptionBreakpoints(); 452b952cd58SEd Maste } 453435933ddSDimitry Andric if (m_objc_language_runtime) { 454435933ddSDimitry Andric m_should_clear_objc_exception_bp = 455435933ddSDimitry Andric !m_objc_language_runtime->ExceptionBreakpointsAreSet(); 456ac7ddfbfSEd Maste m_objc_language_runtime->SetExceptionBreakpoints(); 457ac7ddfbfSEd Maste } 458ac7ddfbfSEd Maste } 459b952cd58SEd Maste } 460ac7ddfbfSEd Maste 461435933ddSDimitry Andric void ThreadPlanCallFunction::ClearBreakpoints() { 462435933ddSDimitry Andric if (m_trap_exceptions) { 463b952cd58SEd Maste if (m_cxx_language_runtime && m_should_clear_cxx_exception_bp) 464ac7ddfbfSEd Maste m_cxx_language_runtime->ClearExceptionBreakpoints(); 465b952cd58SEd Maste if (m_objc_language_runtime && m_should_clear_objc_exception_bp) 466ac7ddfbfSEd Maste m_objc_language_runtime->ClearExceptionBreakpoints(); 467ac7ddfbfSEd Maste } 468b952cd58SEd Maste } 469ac7ddfbfSEd Maste 470435933ddSDimitry Andric bool ThreadPlanCallFunction::BreakpointsExplainStop() { 471ac7ddfbfSEd Maste StopInfoSP stop_info_sp = GetPrivateStopInfo(); 472ac7ddfbfSEd Maste 473435933ddSDimitry Andric if (m_trap_exceptions) { 474ac7ddfbfSEd Maste if ((m_cxx_language_runtime && 475435933ddSDimitry Andric m_cxx_language_runtime->ExceptionBreakpointsExplainStop( 476435933ddSDimitry Andric stop_info_sp)) || 477435933ddSDimitry Andric (m_objc_language_runtime && 478435933ddSDimitry Andric m_objc_language_runtime->ExceptionBreakpointsExplainStop( 479435933ddSDimitry Andric stop_info_sp))) { 480ac7ddfbfSEd Maste Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_STEP)); 481ac7ddfbfSEd Maste if (log) 482435933ddSDimitry Andric log->Printf("ThreadPlanCallFunction::BreakpointsExplainStop - Hit an " 483435933ddSDimitry Andric "exception breakpoint, setting plan complete."); 484ac7ddfbfSEd Maste 485ac7ddfbfSEd Maste SetPlanComplete(false); 486ac7ddfbfSEd Maste 487435933ddSDimitry Andric // If the user has set the ObjC language breakpoint, it would normally get 488435933ddSDimitry Andric // priority over our internal 489435933ddSDimitry Andric // catcher breakpoint, but in this case we can't let that happen, so force 490435933ddSDimitry Andric // the ShouldStop here. 491ac7ddfbfSEd Maste stop_info_sp->OverrideShouldStop(true); 492ac7ddfbfSEd Maste return true; 493ac7ddfbfSEd Maste } 494b952cd58SEd Maste } 495ac7ddfbfSEd Maste 496ac7ddfbfSEd Maste return false; 497ac7ddfbfSEd Maste } 498ac7ddfbfSEd Maste 499435933ddSDimitry Andric void ThreadPlanCallFunction::SetStopOthers(bool new_value) { 5000127ef0fSEd Maste m_subplan_sp->SetStopOthers(new_value); 5010127ef0fSEd Maste } 5020127ef0fSEd Maste 503435933ddSDimitry Andric bool ThreadPlanCallFunction::RestoreThreadState() { 504ac7ddfbfSEd Maste return GetThread().RestoreThreadStateFromCheckpoint(m_stored_thread_state); 505ac7ddfbfSEd Maste } 506ac7ddfbfSEd Maste 507435933ddSDimitry Andric void ThreadPlanCallFunction::SetReturnValue() { 508b91a7dfcSDimitry Andric ProcessSP process_sp(m_thread.GetProcess()); 5099f2f44ceSEd Maste const ABI *abi = process_sp ? process_sp->GetABI().get() : nullptr; 510435933ddSDimitry Andric if (abi && m_return_type.IsValid()) { 511b91a7dfcSDimitry Andric const bool persistent = false; 512435933ddSDimitry Andric m_return_valobj_sp = 513435933ddSDimitry Andric abi->GetReturnValueObject(m_thread, m_return_type, persistent); 514b91a7dfcSDimitry Andric } 515b91a7dfcSDimitry Andric } 516