diff options
Diffstat (limited to 'lldb/source/Target/ThreadPlanStepOut.cpp')
| -rw-r--r-- | lldb/source/Target/ThreadPlanStepOut.cpp | 470 |
1 files changed, 0 insertions, 470 deletions
diff --git a/lldb/source/Target/ThreadPlanStepOut.cpp b/lldb/source/Target/ThreadPlanStepOut.cpp deleted file mode 100644 index 58507a80e601..000000000000 --- a/lldb/source/Target/ThreadPlanStepOut.cpp +++ /dev/null @@ -1,470 +0,0 @@ -//===-- ThreadPlanStepOut.cpp -----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/Target/ThreadPlanStepOut.h" - -// C Includes -// C++ Includes -// Other libraries and framework includes -// Project includes -#include "lldb/Breakpoint/Breakpoint.h" -#include "lldb/lldb-private-log.h" -#include "lldb/Core/Log.h" -#include "lldb/Core/Value.h" -#include "lldb/Core/ValueObjectConstResult.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/RegisterContext.h" -#include "lldb/Target/StopInfo.h" -#include "lldb/Target/Target.h" -#include "lldb/Target/ThreadPlanStepOverRange.h" - -using namespace lldb; -using namespace lldb_private; - -//---------------------------------------------------------------------- -// ThreadPlanStepOut: Step out of the current frame -//---------------------------------------------------------------------- -ThreadPlanStepOut::ThreadPlanStepOut -( - Thread &thread, - SymbolContext *context, - bool first_insn, - bool stop_others, - Vote stop_vote, - Vote run_vote, - uint32_t frame_idx -) : - ThreadPlan (ThreadPlan::eKindStepOut, "Step out", thread, stop_vote, run_vote), - m_step_from_context (context), - m_step_from_insn (LLDB_INVALID_ADDRESS), - m_return_bp_id (LLDB_INVALID_BREAK_ID), - m_return_addr (LLDB_INVALID_ADDRESS), - m_first_insn (first_insn), - m_stop_others (stop_others), - m_step_through_inline_plan_sp(), - m_step_out_plan_sp (), - m_immediate_step_from_function(NULL) - -{ - m_step_from_insn = m_thread.GetRegisterContext()->GetPC(0); - - StackFrameSP return_frame_sp (m_thread.GetStackFrameAtIndex(frame_idx + 1)); - StackFrameSP immediate_return_from_sp (m_thread.GetStackFrameAtIndex (frame_idx)); - - if (!return_frame_sp || !immediate_return_from_sp) - return; // we can't do anything here. ValidatePlan() will return false. - - m_step_out_to_id = return_frame_sp->GetStackID(); - m_immediate_step_from_id = immediate_return_from_sp->GetStackID(); - - StackID frame_zero_id = m_thread.GetStackFrameAtIndex(0)->GetStackID(); - - // If the frame directly below the one we are returning to is inlined, we have to be - // a little more careful. It is non-trivial to determine the real "return code address" for - // an inlined frame, so we have to work our way to that frame and then step out. - if (immediate_return_from_sp && immediate_return_from_sp->IsInlined()) - { - if (frame_idx > 0) - { - // First queue a plan that gets us to this inlined frame, and when we get there we'll queue a second - // plan that walks us out of this frame. - m_step_out_plan_sp.reset (new ThreadPlanStepOut(m_thread, - NULL, - false, - stop_others, - eVoteNoOpinion, - eVoteNoOpinion, - frame_idx - 1)); - m_step_out_plan_sp->SetOkayToDiscard(true); - } - else - { - // If we're already at the inlined frame we're stepping through, then just do that now. - QueueInlinedStepPlan(false); - } - - } - else if (return_frame_sp) - { - // Find the return address and set a breakpoint there: - // FIXME - can we do this more securely if we know first_insn? - - m_return_addr = return_frame_sp->GetFrameCodeAddress().GetLoadAddress(&m_thread.GetProcess()->GetTarget()); - Breakpoint *return_bp = m_thread.CalculateTarget()->CreateBreakpoint (m_return_addr, true).get(); - if (return_bp != NULL) - { - return_bp->SetThreadID(m_thread.GetID()); - m_return_bp_id = return_bp->GetID(); - } - - if (immediate_return_from_sp) - { - const SymbolContext &sc = immediate_return_from_sp->GetSymbolContext(eSymbolContextFunction); - if (sc.function) - { - m_immediate_step_from_function = sc.function; - } - } - } - -} - -void -ThreadPlanStepOut::DidPush() -{ - if (m_step_out_plan_sp) - m_thread.QueueThreadPlan(m_step_out_plan_sp, false); - else if (m_step_through_inline_plan_sp) - m_thread.QueueThreadPlan(m_step_through_inline_plan_sp, false); -} - -ThreadPlanStepOut::~ThreadPlanStepOut () -{ - if (m_return_bp_id != LLDB_INVALID_BREAK_ID) - m_thread.CalculateTarget()->RemoveBreakpointByID(m_return_bp_id); -} - -void -ThreadPlanStepOut::GetDescription (Stream *s, lldb::DescriptionLevel level) -{ - if (level == lldb::eDescriptionLevelBrief) - s->Printf ("step out"); - else - { - if (m_step_out_plan_sp) - s->Printf ("Stepping out to inlined frame so we can walk through it."); - else if (m_step_through_inline_plan_sp) - s->Printf ("Stepping out by stepping through inlined function."); - else - s->Printf ("Stepping out from address 0x%llx to return address 0x%llx using breakpoint site %d", - (uint64_t)m_step_from_insn, - (uint64_t)m_return_addr, - m_return_bp_id); - } -} - -bool -ThreadPlanStepOut::ValidatePlan (Stream *error) -{ - if (m_step_out_plan_sp) - return m_step_out_plan_sp->ValidatePlan (error); - else if (m_step_through_inline_plan_sp) - return m_step_through_inline_plan_sp->ValidatePlan (error); - else if (m_return_bp_id == LLDB_INVALID_BREAK_ID) - { - error->PutCString("Could not create return address breakpoint."); - return false; - } - else - return true; -} - -bool -ThreadPlanStepOut::PlanExplainsStop () -{ - // If one of our child plans just finished, then we do explain the stop. - if (m_step_out_plan_sp) - { - if (m_step_out_plan_sp->MischiefManaged()) - { - // If this one is done, then we are all done. - CalculateReturnValue(); - SetPlanComplete(); - return true; - } - else - return false; - } - else if (m_step_through_inline_plan_sp) - { - if (m_step_through_inline_plan_sp->MischiefManaged()) - return true; - else - return false; - } - - // We don't explain signals or breakpoints (breakpoints that handle stepping in or - // out will be handled by a child plan. - - StopInfoSP stop_info_sp = GetPrivateStopReason(); - if (stop_info_sp) - { - StopReason reason = stop_info_sp->GetStopReason(); - switch (reason) - { - case eStopReasonBreakpoint: - { - // If this is OUR breakpoint, we're fine, otherwise we don't know why this happened... - BreakpointSiteSP site_sp (m_thread.GetProcess()->GetBreakpointSiteList().FindByID (stop_info_sp->GetValue())); - if (site_sp && site_sp->IsBreakpointAtThisSite (m_return_bp_id)) - { - bool done; - - StackID frame_zero_id = m_thread.GetStackFrameAtIndex(0)->GetStackID(); - - if (m_step_out_to_id == frame_zero_id) - done = true; - else if (m_step_out_to_id < frame_zero_id) - { - // Either we stepped past the breakpoint, or the stack ID calculation - // was incorrect and we should probably stop. - done = true; - } - else - { - if (m_immediate_step_from_id < frame_zero_id) - done = true; - else - done = false; - } - - if (done) - { - CalculateReturnValue(); - SetPlanComplete(); - } - - // If there was only one owner, then we're done. But if we also hit some - // user breakpoint on our way out, we should mark ourselves as done, but - // also not claim to explain the stop, since it is more important to report - // the user breakpoint than the step out completion. - - if (site_sp->GetNumberOfOwners() == 1) - return true; - - } - return false; - } - case eStopReasonWatchpoint: - case eStopReasonSignal: - case eStopReasonException: - return false; - - default: - return true; - } - } - return true; -} - -bool -ThreadPlanStepOut::ShouldStop (Event *event_ptr) -{ - if (IsPlanComplete()) - return true; - - bool done; - - StackID frame_zero_id = m_thread.GetStackFrameAtIndex(0)->GetStackID(); - if (frame_zero_id < m_step_out_to_id) - done = false; - else - done = true; - - if (done) - { - CalculateReturnValue(); - SetPlanComplete(); - return true; - } - else - { - if (m_step_out_plan_sp) - { - if (m_step_out_plan_sp->MischiefManaged()) - { - // Now step through the inlined stack we are in: - if (QueueInlinedStepPlan(true)) - { - return false; - } - else - { - CalculateReturnValue(); - SetPlanComplete (); - return true; - } - } - else - return m_step_out_plan_sp->ShouldStop(event_ptr); - } - else if (m_step_through_inline_plan_sp) - { - if (m_step_through_inline_plan_sp->MischiefManaged()) - { - // We don't calculate the return value here because we don't know how to. - // But in case we had a return value sitting around from our process in - // getting here, let's clear it out. - m_return_valobj_sp.reset(); - SetPlanComplete(); - return true; - } - else - return m_step_through_inline_plan_sp->ShouldStop(event_ptr); - } - else - return false; - } -} - -bool -ThreadPlanStepOut::StopOthers () -{ - return m_stop_others; -} - -StateType -ThreadPlanStepOut::GetPlanRunState () -{ - return eStateRunning; -} - -bool -ThreadPlanStepOut::WillResume (StateType resume_state, bool current_plan) -{ - ThreadPlan::WillResume (resume_state, current_plan); - if (m_step_out_plan_sp || m_step_through_inline_plan_sp) - return true; - - if (m_return_bp_id == LLDB_INVALID_BREAK_ID) - return false; - - if (current_plan) - { - Breakpoint *return_bp = m_thread.CalculateTarget()->GetBreakpointByID(m_return_bp_id).get(); - if (return_bp != NULL) - return_bp->SetEnabled (true); - } - return true; -} - -bool -ThreadPlanStepOut::WillStop () -{ - if (m_return_bp_id != LLDB_INVALID_BREAK_ID) - { - Breakpoint *return_bp = m_thread.CalculateTarget()->GetBreakpointByID(m_return_bp_id).get(); - if (return_bp != NULL) - return_bp->SetEnabled (false); - } - - return true; -} - -bool -ThreadPlanStepOut::MischiefManaged () -{ - if (IsPlanComplete()) - { - // Did I reach my breakpoint? If so I'm done. - // - // I also check the stack depth, since if we've blown past the breakpoint for some - // reason and we're now stopping for some other reason altogether, then we're done - // with this step out operation. - - LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); - if (log) - log->Printf("Completed step out plan."); - if (m_return_bp_id != LLDB_INVALID_BREAK_ID) - { - m_thread.CalculateTarget()->RemoveBreakpointByID (m_return_bp_id); - m_return_bp_id = LLDB_INVALID_BREAK_ID; - } - - ThreadPlan::MischiefManaged (); - return true; - } - else - { - return false; - } -} - -bool -ThreadPlanStepOut::QueueInlinedStepPlan (bool queue_now) -{ - // Now figure out the range of this inlined block, and set up a "step through range" - // plan for that. If we've been provided with a context, then use the block in that - // context. - StackFrameSP immediate_return_from_sp (m_thread.GetStackFrameAtIndex (0)); - if (!immediate_return_from_sp) - return false; - - LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); - if (log) - { - StreamString s; - immediate_return_from_sp->Dump(&s, true, false); - log->Printf("Queuing inlined frame to step past: %s.", s.GetData()); - } - - Block *from_block = immediate_return_from_sp->GetFrameBlock(); - if (from_block) - { - Block *inlined_block = from_block->GetContainingInlinedBlock(); - if (inlined_block) - { - size_t num_ranges = inlined_block->GetNumRanges(); - AddressRange inline_range; - if (inlined_block->GetRangeAtIndex(0, inline_range)) - { - SymbolContext inlined_sc; - inlined_block->CalculateSymbolContext(&inlined_sc); - RunMode run_mode = m_stop_others ? lldb::eOnlyThisThread : lldb::eAllThreads; - ThreadPlanStepOverRange *step_through_inline_plan_ptr = new ThreadPlanStepOverRange(m_thread, - inline_range, - inlined_sc, - run_mode); - step_through_inline_plan_ptr->SetOkayToDiscard(true); - StreamString errors; - if (!step_through_inline_plan_ptr->ValidatePlan(&errors)) - { - //FIXME: Log this failure. - delete step_through_inline_plan_ptr; - return false; - } - - for (size_t i = 1; i < num_ranges; i++) - { - if (inlined_block->GetRangeAtIndex (i, inline_range)) - step_through_inline_plan_ptr->AddRange (inline_range); - } - m_step_through_inline_plan_sp.reset (step_through_inline_plan_ptr); - if (queue_now) - m_thread.QueueThreadPlan (m_step_through_inline_plan_sp, false); - return true; - } - } - } - - return false; -} - -void -ThreadPlanStepOut::CalculateReturnValue () -{ - if (m_return_valobj_sp) - return; - - if (m_immediate_step_from_function != NULL) - { - Type *return_type = m_immediate_step_from_function->GetType(); - lldb::clang_type_t return_clang_type = m_immediate_step_from_function->GetReturnClangType(); - if (return_type && return_clang_type) - { - ClangASTType ast_type (return_type->GetClangAST(), return_clang_type); - - lldb::ABISP abi_sp = m_thread.GetProcess()->GetABI(); - if (abi_sp) - { - m_return_valobj_sp = abi_sp->GetReturnValueObject(m_thread, ast_type); - } - } - } -} |
