diff options
-rw-r--r-- | lldb/include/lldb/Breakpoint/BreakpointSiteList.h | 17 | ||||
-rw-r--r-- | lldb/include/lldb/Core/Disassembler.h | 6 | ||||
-rw-r--r-- | lldb/include/lldb/Target/ThreadPlan.h | 51 | ||||
-rw-r--r-- | lldb/include/lldb/Target/ThreadPlanStepInRange.h | 3 | ||||
-rw-r--r-- | lldb/include/lldb/Target/ThreadPlanStepOverRange.h | 1 | ||||
-rw-r--r-- | lldb/include/lldb/Target/ThreadPlanStepRange.h | 35 | ||||
-rw-r--r-- | lldb/include/lldb/Target/ThreadPlanTracer.h | 2 | ||||
-rw-r--r-- | lldb/include/lldb/lldb-forward.h | 1 | ||||
-rw-r--r-- | lldb/source/Breakpoint/BreakpointSiteList.cpp | 10 | ||||
-rw-r--r-- | lldb/source/Core/Disassembler.cpp | 34 | ||||
-rw-r--r-- | lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp | 24 | ||||
-rw-r--r-- | lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp | 25 | ||||
-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 |
16 files changed, 334 insertions, 178 deletions
diff --git a/lldb/include/lldb/Breakpoint/BreakpointSiteList.h b/lldb/include/lldb/Breakpoint/BreakpointSiteList.h index 005246815a9..76c1f52b058 100644 --- a/lldb/include/lldb/Breakpoint/BreakpointSiteList.h +++ b/lldb/include/lldb/Breakpoint/BreakpointSiteList.h @@ -112,6 +112,23 @@ public: //------------------------------------------------------------------ lldb::break_id_t FindIDByAddress (lldb::addr_t addr); + + //------------------------------------------------------------------ + /// Returns whether the breakpoint site \a bp_site_id has \a bp_id + // as one of its owners. + /// + /// @param[in] bp_site_id + /// The breakpoint site id to query. + /// + /// @param[in] bp_id + /// The breakpoint id to look for in \a bp_site_id. + /// + /// @result + /// True if \a bp_site_id exists in the site list AND \a bp_id is one of the + /// owners of that site. + //------------------------------------------------------------------ + bool + BreakpointSiteContainsBreakpoint (lldb::break_id_t bp_site_id, lldb::break_id_t bp_id); //------------------------------------------------------------------ /// Returns a shared pointer to the breakpoint site with index \a i. diff --git a/lldb/include/lldb/Core/Disassembler.h b/lldb/include/lldb/Core/Disassembler.h index 6d09b9f8c1d..8553ded8211 100644 --- a/lldb/include/lldb/Core/Disassembler.h +++ b/lldb/include/lldb/Core/Disassembler.h @@ -163,6 +163,12 @@ public: lldb::InstructionSP GetInstructionAtIndex (uint32_t idx) const; + + uint32_t + GetIndexOfNextBranchInstruction(uint32_t start) const; + + uint32_t + GetIndexOfInstructionAtLoadAddress (lldb::addr_t load_addr, Target &target); void Clear(); diff --git a/lldb/include/lldb/Target/ThreadPlan.h b/lldb/include/lldb/Target/ThreadPlan.h index a5604af40cb..a814c46ff03 100644 --- a/lldb/include/lldb/Target/ThreadPlan.h +++ b/lldb/include/lldb/Target/ThreadPlan.h @@ -18,6 +18,8 @@ #include "lldb/lldb-private.h" #include "lldb/Core/UserID.h" #include "lldb/Host/Mutex.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadPlanTracer.h" #include "lldb/Target/StopInfo.h" @@ -223,8 +225,11 @@ public: /// A const char * pointer to the thread plan's name. //------------------------------------------------------------------ const char * - GetName () const; - + GetName () const + { + return m_name.c_str(); + } + //------------------------------------------------------------------ /// Returns the Thread that is using this thread plan. /// @@ -232,10 +237,28 @@ public: /// A pointer to the thread plan's owning thread. //------------------------------------------------------------------ Thread & - GetThread(); + GetThread() + { + return m_thread; + } const Thread & - GetThread() const; + GetThread() const + { + return m_thread; + } + + Target & + GetTarget() + { + return m_thread.GetProcess()->GetTarget(); + } + + const Target & + GetTarget() const + { + return m_thread.GetProcess()->GetTarget(); + } //------------------------------------------------------------------ /// Print a description of this thread to the stream \a s. @@ -332,10 +355,16 @@ public: MischiefManaged (); bool - GetPrivate (); + GetPrivate () + { + return m_plan_private; + } void - SetPrivate (bool input); + SetPrivate (bool input) + { + m_plan_private = input; + } virtual void DidPush(); @@ -345,7 +374,10 @@ public: // This pushes \a plan onto the plan stack of the current plan's thread. void - PushPlan (lldb::ThreadPlanSP &thread_plan_sp); + PushPlan (lldb::ThreadPlanSP &thread_plan_sp) + { + m_thread.PushPlan (thread_plan_sp); + } ThreadPlanKind GetKind() const { @@ -403,7 +435,10 @@ protected: // GetPreviousPlan protected, but only friend ThreadPlan to thread. ThreadPlan * - GetPreviousPlan (); + GetPreviousPlan () + { + return m_thread.GetPreviousPlan (this); + } // This forwards the private Thread::GetPrivateStopReason which is generally what // ThreadPlan's need to know. diff --git a/lldb/include/lldb/Target/ThreadPlanStepInRange.h b/lldb/include/lldb/Target/ThreadPlanStepInRange.h index 2d3ca2d03e9..7eb571777d5 100644 --- a/lldb/include/lldb/Target/ThreadPlanStepInRange.h +++ b/lldb/include/lldb/Target/ThreadPlanStepInRange.h @@ -43,9 +43,6 @@ public: void SetAvoidRegexp(const char *name); - virtual bool - PlanExplainsStop (); - static ThreadPlan * DefaultShouldStopHereCallback (ThreadPlan *current_plan, Flags &flags, void *baton); diff --git a/lldb/include/lldb/Target/ThreadPlanStepOverRange.h b/lldb/include/lldb/Target/ThreadPlanStepOverRange.h index b57bddb4b3f..8190b81d14f 100644 --- a/lldb/include/lldb/Target/ThreadPlanStepOverRange.h +++ b/lldb/include/lldb/Target/ThreadPlanStepOverRange.h @@ -33,7 +33,6 @@ public: virtual ~ThreadPlanStepOverRange (); - virtual bool PlanExplainsStop (); virtual void GetDescription (Stream *s, lldb::DescriptionLevel level); virtual bool ShouldStop (Event *event_ptr); virtual bool diff --git a/lldb/include/lldb/Target/ThreadPlanStepRange.h b/lldb/include/lldb/Target/ThreadPlanStepRange.h index 89410ce962f..dc1021d71ad 100644 --- a/lldb/include/lldb/Target/ThreadPlanStepRange.h +++ b/lldb/include/lldb/Target/ThreadPlanStepRange.h @@ -42,6 +42,9 @@ public: virtual lldb::StateType GetPlanRunState (); virtual bool WillStop (); virtual bool MischiefManaged (); + virtual bool PlanExplainsStop (); + virtual void DidPush (); + void AddRange(const AddressRange &new_range); @@ -52,15 +55,35 @@ protected: bool InSymbol(); void DumpRanges (Stream *s); - SymbolContext m_addr_context; + Disassembler * + GetDisassembler (); + + InstructionList * + GetInstructionsForAddress(lldb::addr_t addr, size_t &range_index, size_t &insn_offset); + + // Pushes a plan to proceed through the next section of instructions in the range - usually just a RunToAddress + // plan to run to the next branch. Returns true if it pushed such a plan. If there was no available 'quick run' + // plan, then just single step. + bool + SetNextBranchBreakpoint (); + + void + ClearNextBranchBreakpoint(); + + bool + NextRangeBreakpointExplainsStop (lldb::StopInfoSP stop_info_sp); + + SymbolContext m_addr_context; std::vector<AddressRange> m_address_ranges; - lldb::RunMode m_stop_others; - StackID m_stack_id; // Use the stack ID so we can tell step out from step in. - bool m_no_more_plans; // Need this one so we can tell if we stepped into a call, but can't continue, - // in which case we are done. - bool m_first_run_event; // We want to broadcast only one running event, our first. + lldb::RunMode m_stop_others; + StackID m_stack_id; // Use the stack ID so we can tell step out from step in. + bool m_no_more_plans; // Need this one so we can tell if we stepped into a call, + // but can't continue, in which case we are done. + bool m_first_run_event; // We want to broadcast only one running event, our first. + lldb::BreakpointSP m_next_branch_bp_sp; private: + std::vector<lldb::DisassemblerSP> m_instruction_ranges; DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepRange); }; diff --git a/lldb/include/lldb/Target/ThreadPlanTracer.h b/lldb/include/lldb/Target/ThreadPlanTracer.h index bd45ca491c1..2a483cbfb55 100644 --- a/lldb/include/lldb/Target/ThreadPlanTracer.h +++ b/lldb/include/lldb/Target/ThreadPlanTracer.h @@ -90,6 +90,8 @@ protected: Stream * GetLogStream (); + + virtual void Log(); private: diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h index 364b3b362ea..c7dd37e1445 100644 --- a/lldb/include/lldb/lldb-forward.h +++ b/lldb/include/lldb/lldb-forward.h @@ -99,6 +99,7 @@ class InlineFunctionInfo; class InputReader; class InstanceSettings; class Instruction; +class InstructionList; class LanguageRuntime; class LineTable; class Listener; diff --git a/lldb/source/Breakpoint/BreakpointSiteList.cpp b/lldb/source/Breakpoint/BreakpointSiteList.cpp index 758521dd044..bacb388b377 100644 --- a/lldb/source/Breakpoint/BreakpointSiteList.cpp +++ b/lldb/source/Breakpoint/BreakpointSiteList.cpp @@ -164,6 +164,16 @@ BreakpointSiteList::FindByAddress (lldb::addr_t addr) return found_sp; } +bool +BreakpointSiteList::BreakpointSiteContainsBreakpoint (lldb::break_id_t bp_site_id, lldb::break_id_t bp_id) +{ + collection::const_iterator pos = GetIDConstIterator(bp_site_id); + if (pos != m_bp_site_list.end()) + pos->second->IsBreakpointAtThisSite (bp_id); + + return false; +} + void BreakpointSiteList::Dump (Stream *s) const { diff --git a/lldb/source/Core/Disassembler.cpp b/lldb/source/Core/Disassembler.cpp index 2882da90a79..854cbc04762 100644 --- a/lldb/source/Core/Disassembler.cpp +++ b/lldb/source/Core/Disassembler.cpp @@ -902,6 +902,40 @@ InstructionList::Append (lldb::InstructionSP &inst_sp) m_instructions.push_back(inst_sp); } +uint32_t +InstructionList::GetIndexOfNextBranchInstruction(uint32_t start) const +{ + size_t num_instructions = m_instructions.size(); + + uint32_t next_branch = UINT32_MAX; + for (size_t i = start; i < num_instructions; i++) + { + if (m_instructions[i]->DoesBranch()) + { + next_branch = i; + break; + } + } + return next_branch; +} + +uint32_t +InstructionList::GetIndexOfInstructionAtLoadAddress (lldb::addr_t load_addr, Target &target) +{ + Address address; + address.SetLoadAddress(load_addr, &target); + uint32_t num_instructions = m_instructions.size(); + uint32_t index = UINT32_MAX; + for (int i = 0; i < num_instructions; i++) + { + if (m_instructions[i]->GetAddress() == address) + { + index = i; + break; + } + } + return index; +} size_t Disassembler::ParseInstructions diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp index 22eeb2e2825..0f8d70487b4 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp @@ -364,27 +364,7 @@ ItaniumABILanguageRuntime::ExceptionBreakpointsExplainStop (lldb::StopInfoSP sto return false; uint64_t break_site_id = stop_reason->GetValue(); - lldb::BreakpointSiteSP bp_site_sp = m_process->GetBreakpointSiteList().FindByID(break_site_id); + return m_process->GetBreakpointSiteList().BreakpointSiteContainsBreakpoint(break_site_id, + m_cxx_exception_bp_sp->GetID()); - if (!bp_site_sp) - return false; - - uint32_t num_owners = bp_site_sp->GetNumberOfOwners(); - - break_id_t cxx_exception_bid; - - if (!m_cxx_exception_bp_sp) - return false; - - cxx_exception_bid = m_cxx_exception_bp_sp->GetID(); - - for (uint32_t i = 0; i < num_owners; i++) - { - break_id_t bid = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().GetID(); - - if (bid == cxx_exception_bid) - return true; - } - - return false; } diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp index 84042b4b850..5a341307d65 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp @@ -328,29 +328,8 @@ AppleObjCRuntime::ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason) return false; uint64_t break_site_id = stop_reason->GetValue(); - lldb::BreakpointSiteSP bp_site_sp = m_process->GetBreakpointSiteList().FindByID(break_site_id); - - if (!bp_site_sp) - return false; - - uint32_t num_owners = bp_site_sp->GetNumberOfOwners(); - - break_id_t objc_exception_bid; - - if (!m_objc_exception_bp_sp) - return false; - - objc_exception_bid = m_objc_exception_bp_sp->GetID(); - - for (uint32_t i = 0; i < num_owners; i++) - { - break_id_t bid = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().GetID(); - - if (bid == objc_exception_bid) - return true; - } - - return false; + return m_process->GetBreakpointSiteList().BreakpointSiteContainsBreakpoint (break_site_id, + m_objc_exception_bp_sp->GetID()); } bool 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 |