diff options
Diffstat (limited to 'lldb/source/Target')
-rw-r--r-- | lldb/source/Target/ThreadPlan.cpp | 43 | ||||
-rw-r--r-- | lldb/source/Target/ThreadPlanStepInRange.cpp | 48 | ||||
-rw-r--r-- | lldb/source/Target/ThreadPlanStepOverRange.cpp | 55 | ||||
-rw-r--r-- | lldb/source/Target/ThreadPlanStepRange.cpp | 157 |
4 files changed, 188 insertions, 115 deletions
diff --git a/lldb/source/Target/ThreadPlan.cpp b/lldb/source/Target/ThreadPlan.cpp index e47a4b59afe..8e9cb477447 100644 --- a/lldb/source/Target/ThreadPlan.cpp +++ b/lldb/source/Target/ThreadPlan.cpp @@ -48,25 +48,6 @@ ThreadPlan::~ThreadPlan() { } -const char * -ThreadPlan::GetName () const -{ - return m_name.c_str(); -} - -Thread & -ThreadPlan::GetThread() -{ - return m_thread; -} - - -const Thread & -ThreadPlan::GetThread() const -{ - return m_thread; -} - bool ThreadPlan::IsPlanComplete () { @@ -187,30 +168,6 @@ ThreadPlan::WillPop() { } -void -ThreadPlan::PushPlan (ThreadPlanSP &thread_plan_sp) -{ - m_thread.PushPlan (thread_plan_sp); -} - -ThreadPlan * -ThreadPlan::GetPreviousPlan () -{ - return m_thread.GetPreviousPlan (this); -} - -void -ThreadPlan::SetPrivate (bool input) -{ - m_plan_private = input; -} - -bool -ThreadPlan::GetPrivate (void) -{ - return m_plan_private; -} - bool ThreadPlan::OkayToDiscard() { diff --git a/lldb/source/Target/ThreadPlanStepInRange.cpp b/lldb/source/Target/ThreadPlanStepInRange.cpp index e7d5f8189a7..9fbca6b03f7 100644 --- a/lldb/source/Target/ThreadPlanStepInRange.cpp +++ b/lldb/source/Target/ThreadPlanStepInRange.cpp @@ -68,37 +68,6 @@ ThreadPlanStepInRange::GetDescription (Stream *s, lldb::DescriptionLevel level) } bool -ThreadPlanStepInRange::PlanExplainsStop () -{ - // We always explain a stop. Either we've just done a single step, in which - // case we'll do our ordinary processing, or we stopped for some - // reason that isn't handled by our sub-plans, in which case we want to just stop right - // away. - - LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); - StopInfoSP stop_info_sp = GetPrivateStopReason(); - if (stop_info_sp) - { - StopReason reason = stop_info_sp->GetStopReason(); - - switch (reason) - { - case eStopReasonBreakpoint: - case eStopReasonWatchpoint: - case eStopReasonSignal: - case eStopReasonException: - if (log) - log->PutCString ("ThreadPlanStepInRange got asked if it explains the stop for some reason other than step."); - SetPlanComplete(); - break; - default: - break; - } - } - return true; -} - -bool ThreadPlanStepInRange::ShouldStop (Event *event_ptr) { LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); @@ -115,10 +84,6 @@ ThreadPlanStepInRange::ShouldStop (Event *event_ptr) if (IsPlanComplete()) return true; - // If we're still in the range, keep going. - if (InRange()) - return false; - ThreadPlan* new_plan = NULL; // Stepping through should be done stopping other threads in general, since we're setting a breakpoint and @@ -148,7 +113,7 @@ ThreadPlanStepInRange::ShouldStop (Event *event_ptr) } } - else if (frame_order != eFrameCompareYounger && InSymbol()) + else if (frame_order == eFrameCompareEqual && InSymbol()) { // If we are not in a place we should step through, we're done. // One tricky bit here is that some stubs don't push a frame, so we have to check @@ -156,11 +121,22 @@ ThreadPlanStepInRange::ShouldStop (Event *event_ptr) // However, if the frame is the same, and we are still in the symbol we started // in, the we don't need to do this. This first check isn't strictly necessary, // but it is more efficient. + + // If we're still in the range, keep going, either by running to the next branch breakpoint, or by + // stepping. + if (InRange()) + { + SetNextBranchBreakpoint(); + return false; + } SetPlanComplete(); return true; } + // If we get to this point, we're not going to use a previously set "next branch" breakpoint, so delete it: + ClearNextBranchBreakpoint(); + // We may have set the plan up above in the FrameIsOlder section: if (new_plan == NULL) diff --git a/lldb/source/Target/ThreadPlanStepOverRange.cpp b/lldb/source/Target/ThreadPlanStepOverRange.cpp index 8b4907f863f..54fe8ea62a8 100644 --- a/lldb/source/Target/ThreadPlanStepOverRange.cpp +++ b/lldb/source/Target/ThreadPlanStepOverRange.cpp @@ -63,31 +63,6 @@ ThreadPlanStepOverRange::GetDescription (Stream *s, lldb::DescriptionLevel level } bool -ThreadPlanStepOverRange::PlanExplainsStop () -{ - // 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: - case eStopReasonWatchpoint: - case eStopReasonSignal: - case eStopReasonException: - return false; - default: - return true; - } - } - return true; -} - - -bool ThreadPlanStepOverRange::ShouldStop (Event *event_ptr) { LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); @@ -100,10 +75,6 @@ ThreadPlanStepOverRange::ShouldStop (Event *event_ptr) log->Printf("ThreadPlanStepOverRange reached %s.", s.GetData()); } - // If we're still in the range, keep going. - if (InRange()) - return false; - // If we're out of the range but in the same frame or in our caller's frame // then we should stop. // When stepping out we only step if we are forcing running one thread. @@ -158,15 +129,29 @@ ThreadPlanStepOverRange::ShouldStop (Event *event_ptr) } } } - else if (!InSymbol()) + else { - // This one is a little tricky. Sometimes we may be in a stub or something similar, - // in which case we need to get out of there. But if we are in a stub then it's - // likely going to be hard to get out from here. It is probably easiest to step into the - // stub, and then it will be straight-forward to step out. - new_plan = m_thread.QueueThreadPlanForStepThrough (false, stop_others); + // If we're still in the range, keep going. + if (InRange()) + { + SetNextBranchBreakpoint(); + return false; + } + + + if (!InSymbol()) + { + // This one is a little tricky. Sometimes we may be in a stub or something similar, + // in which case we need to get out of there. But if we are in a stub then it's + // likely going to be hard to get out from here. It is probably easiest to step into the + // stub, and then it will be straight-forward to step out. + new_plan = m_thread.QueueThreadPlanForStepThrough (false, stop_others); + } } + // If we get to this point, we're not going to use a previously set "next branch" breakpoint, so delete it: + ClearNextBranchBreakpoint(); + if (new_plan == NULL) m_no_more_plans = true; else diff --git a/lldb/source/Target/ThreadPlanStepRange.cpp b/lldb/source/Target/ThreadPlanStepRange.cpp index b504e1f18db..59f760c9e6b 100644 --- a/lldb/source/Target/ThreadPlanStepRange.cpp +++ b/lldb/source/Target/ThreadPlanStepRange.cpp @@ -15,14 +15,18 @@ // Project includes #include "lldb/lldb-private-log.h" +#include "lldb/Core/Disassembler.h" #include "lldb/Core/Log.h" #include "lldb/Core/Stream.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/Symbol.h" +#include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/StopInfo.h" +#include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadPlanRunToAddress.h" using namespace lldb; using namespace lldb_private; @@ -53,6 +57,14 @@ ThreadPlanStepRange::ThreadPlanStepRange (ThreadPlanKind kind, ThreadPlanStepRange::~ThreadPlanStepRange () { + ClearNextBranchBreakpoint(); +} + +void +ThreadPlanStepRange::DidPush () +{ + // See if we can find a "next range" breakpoint: + SetNextBranchBreakpoint(); } bool @@ -79,6 +91,7 @@ ThreadPlanStepRange::AddRange(const AddressRange &new_range) // condense the ranges if they overlap, though I don't think it is likely // to be very important. m_address_ranges.push_back (new_range); + m_instruction_ranges.push_back (DisassemblerSP()); } void @@ -230,6 +243,145 @@ ThreadPlanStepRange::StopOthers () return false; } +InstructionList * +ThreadPlanStepRange::GetInstructionsForAddress(lldb::addr_t addr, size_t &range_index, size_t &insn_offset) +{ + size_t num_ranges = m_address_ranges.size(); + for (size_t i = 0; i < num_ranges; i++) + { + if (m_address_ranges[i].ContainsLoadAddress(addr, &GetTarget())) + { + // Some joker added a zero size range to the stepping range... + if (m_address_ranges[i].GetByteSize() == 0) + return NULL; + + if (!m_instruction_ranges[i]) + { + //Disassemble the address range given: + ExecutionContext exe_ctx (m_thread.GetProcess()); + m_instruction_ranges[i] = Disassembler::DisassembleRange(GetTarget().GetArchitecture(), + NULL, + exe_ctx, + m_address_ranges[i]); + + } + if (!m_instruction_ranges[i]) + return NULL; + else + { + // Find where we are in the instruction list as well. If we aren't at an instruction, + // return NULL. In this case, we're probably lost, and shouldn't try to do anything fancy. + + insn_offset = m_instruction_ranges[i]->GetInstructionList().GetIndexOfInstructionAtLoadAddress(addr, GetTarget()); + if (insn_offset == UINT32_MAX) + return NULL; + else + { + range_index = i; + return &m_instruction_ranges[i]->GetInstructionList(); + } + } + } + } + return NULL; +} + +void +ThreadPlanStepRange::ClearNextBranchBreakpoint() +{ + if (m_next_branch_bp_sp) + { + GetTarget().RemoveBreakpointByID (m_next_branch_bp_sp->GetID()); + m_next_branch_bp_sp.reset(); + } +} + +bool +ThreadPlanStepRange::SetNextBranchBreakpoint () +{ + // Stepping through ranges using breakpoints doesn't work yet, but with this off we fall back to instruction + // single stepping. + return false; + // Always clear the next branch breakpoint, we don't want to leave one of these stranded. + ClearNextBranchBreakpoint(); + lldb::addr_t cur_addr = GetThread().GetRegisterContext()->GetPC(); + // Find the current address in our address ranges, and fetch the disassembly if we haven't already: + size_t pc_index; + size_t range_index; + InstructionList *instructions = GetInstructionsForAddress (cur_addr, range_index, pc_index); + if (instructions == NULL) + return false; + else + { + uint32_t branch_index; + branch_index = instructions->GetIndexOfNextBranchInstruction (pc_index); + + Address run_to_address; + + // If we didn't find a branch, run to the end of the range. + if (branch_index == UINT32_MAX) + { + branch_index = instructions->GetSize() - 2; + } + if (branch_index - pc_index > 1) + { + const bool is_internal = true; + run_to_address = instructions->GetInstructionAtIndex(branch_index)->GetAddress(); + m_next_branch_bp_sp = GetTarget().CreateBreakpoint(run_to_address, is_internal); + m_next_branch_bp_sp->SetThreadID(m_thread.GetID()); + return true; + } + } + return false; +} + +bool +ThreadPlanStepRange::NextRangeBreakpointExplainsStop (lldb::StopInfoSP stop_info_sp) +{ + if (!m_next_branch_bp_sp) + return false; + + break_id_t bp_site_id = stop_info_sp->GetValue(); + BreakpointSiteSP bp_site_sp = m_thread.GetProcess()->GetBreakpointSiteList().FindByID(bp_site_id); + if (!bp_site_sp->IsBreakpointAtThisSite (m_next_branch_bp_sp->GetID())) + return false; + else + return bp_site_sp->GetNumberOfOwners() == 1; +} + +bool +ThreadPlanStepRange::PlanExplainsStop () +{ + // We always explain a stop. Either we've just done a single step, in which + // case we'll do our ordinary processing, or we stopped for some + // reason that isn't handled by our sub-plans, in which case we want to just stop right + // away. + + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); + StopInfoSP stop_info_sp = GetPrivateStopReason(); + if (stop_info_sp) + { + StopReason reason = stop_info_sp->GetStopReason(); + + switch (reason) + { + case eStopReasonBreakpoint: + if (NextRangeBreakpointExplainsStop(stop_info_sp)) + return true; + case eStopReasonWatchpoint: + case eStopReasonSignal: + case eStopReasonException: + if (log) + log->PutCString ("ThreadPlanStepInRange got asked if it explains the stop for some reason other than step."); + SetPlanComplete(); + break; + default: + break; + } + } + return true; +} + bool ThreadPlanStepRange::WillStop () { @@ -239,7 +391,10 @@ ThreadPlanStepRange::WillStop () StateType ThreadPlanStepRange::GetPlanRunState () { - return eStateStepping; + if (m_next_branch_bp_sp) + return eStateRunning; + else + return eStateStepping; } bool |