summaryrefslogtreecommitdiffstats
path: root/lldb/source/Target
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Target')
-rw-r--r--lldb/source/Target/ThreadPlan.cpp43
-rw-r--r--lldb/source/Target/ThreadPlanStepInRange.cpp48
-rw-r--r--lldb/source/Target/ThreadPlanStepOverRange.cpp55
-rw-r--r--lldb/source/Target/ThreadPlanStepRange.cpp157
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
OpenPOWER on IntegriCloud