diff options
-rw-r--r-- | lldb/include/lldb/Target/StackID.h | 2 | ||||
-rw-r--r-- | lldb/include/lldb/Target/ThreadPlan.h | 1 | ||||
-rw-r--r-- | lldb/include/lldb/Target/ThreadPlanStepOut.h | 5 | ||||
-rw-r--r-- | lldb/include/lldb/Target/ThreadPlanStepRange.h | 4 | ||||
-rw-r--r-- | lldb/include/lldb/Target/ThreadPlanStepUntil.h | 2 | ||||
-rw-r--r-- | lldb/include/lldb/lldb-enumerations.h | 15 | ||||
-rw-r--r-- | lldb/source/Target/StackID.cpp | 6 | ||||
-rw-r--r-- | lldb/source/Target/ThreadPlan.cpp | 6 | ||||
-rw-r--r-- | lldb/source/Target/ThreadPlanStepInRange.cpp | 10 | ||||
-rw-r--r-- | lldb/source/Target/ThreadPlanStepOut.cpp | 55 | ||||
-rw-r--r-- | lldb/source/Target/ThreadPlanStepOverRange.cpp | 39 | ||||
-rw-r--r-- | lldb/source/Target/ThreadPlanStepRange.cpp | 70 | ||||
-rw-r--r-- | lldb/source/Target/ThreadPlanStepUntil.cpp | 54 |
13 files changed, 175 insertions, 94 deletions
diff --git a/lldb/include/lldb/Target/StackID.h b/lldb/include/lldb/Target/StackID.h index 15f24dd4725..7e713c73d97 100644 --- a/lldb/include/lldb/Target/StackID.h +++ b/lldb/include/lldb/Target/StackID.h @@ -140,6 +140,8 @@ protected: bool operator== (const StackID& lhs, const StackID& rhs); bool operator!= (const StackID& lhs, const StackID& rhs); + +// frame_id_1 < frame_id_2 means "frame_id_1 is YOUNGER than frame_id_2" bool operator< (const StackID& lhs, const StackID& rhs); } // namespace lldb_private diff --git a/lldb/include/lldb/Target/ThreadPlan.h b/lldb/include/lldb/Target/ThreadPlan.h index e31071bc9b9..a5604af40cb 100644 --- a/lldb/include/lldb/Target/ThreadPlan.h +++ b/lldb/include/lldb/Target/ThreadPlan.h @@ -423,7 +423,6 @@ protected: virtual lldb::StateType GetPlanRunState () = 0; - Thread &m_thread; Vote m_stop_vote; Vote m_run_vote; diff --git a/lldb/include/lldb/Target/ThreadPlanStepOut.h b/lldb/include/lldb/Target/ThreadPlanStepOut.h index b96be5d29a3..b08abfc24e7 100644 --- a/lldb/include/lldb/Target/ThreadPlanStepOut.h +++ b/lldb/include/lldb/Target/ThreadPlanStepOut.h @@ -50,11 +50,12 @@ public: protected: bool QueueInlinedStepPlan (bool queue_now); - + private: SymbolContext *m_step_from_context; lldb::addr_t m_step_from_insn; - uint32_t m_stack_depth; + StackID m_step_out_to_id; + StackID m_immediate_step_from_id; lldb::break_id_t m_return_bp_id; lldb::addr_t m_return_addr; bool m_first_insn; diff --git a/lldb/include/lldb/Target/ThreadPlanStepRange.h b/lldb/include/lldb/Target/ThreadPlanStepRange.h index 88675c8d293..89410ce962f 100644 --- a/lldb/include/lldb/Target/ThreadPlanStepRange.h +++ b/lldb/include/lldb/Target/ThreadPlanStepRange.h @@ -48,15 +48,13 @@ public: protected: bool InRange(); - bool FrameIsYounger(); - bool FrameIsOlder(); + lldb::FrameComparison CompareCurrentFrameToStartFrame(); bool InSymbol(); void DumpRanges (Stream *s); SymbolContext m_addr_context; std::vector<AddressRange> m_address_ranges; lldb::RunMode m_stop_others; - uint32_t m_stack_depth; 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. diff --git a/lldb/include/lldb/Target/ThreadPlanStepUntil.h b/lldb/include/lldb/Target/ThreadPlanStepUntil.h index fa0c525b001..17002e47254 100644 --- a/lldb/include/lldb/Target/ThreadPlanStepUntil.h +++ b/lldb/include/lldb/Target/ThreadPlanStepUntil.h @@ -51,7 +51,7 @@ protected: private: - uint64_t m_stack_depth; + StackID m_stack_id; lldb::addr_t m_step_from_insn; lldb::break_id_t m_return_bp_id; lldb::addr_t m_return_addr; diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h index f8aba437dc0..8e1f0e9f299 100644 --- a/lldb/include/lldb/lldb-enumerations.h +++ b/lldb/include/lldb/lldb-enumerations.h @@ -615,7 +615,20 @@ namespace lldb { eTypeOptionShowOneLiner = (1u << 5), eTypeOptionHideNames = (1u << 6) } TypeOptions; - + + //---------------------------------------------------------------------- + // This is the return value for frame comparisons. When frame A pushes + // frame B onto the stack, frame A is OLDER than frame B. + //---------------------------------------------------------------------- + typedef enum FrameComparison + { + eFrameCompareInvalid, + eFrameCompareUnknown, + eFrameCompareEqual, + eFrameCompareYounger, + eFrameCompareOlder + } FrameComparison; + } // namespace lldb diff --git a/lldb/source/Target/StackID.cpp b/lldb/source/Target/StackID.cpp index c430c3a38a4..1b55b722d3c 100644 --- a/lldb/source/Target/StackID.cpp +++ b/lldb/source/Target/StackID.cpp @@ -75,6 +75,12 @@ lldb_private::operator< (const StackID& lhs, const StackID& rhs) const lldb::addr_t lhs_cfa = lhs.GetCallFrameAddress(); const lldb::addr_t rhs_cfa = rhs.GetCallFrameAddress(); + // FIXME: We are assuming that the stacks grow downward in memory. That's not necessary, but true on + // all the machines we care about at present. If this changes, we'll have to deal with that. The ABI is the + // agent who knows this ordering, but the StackID has no access to the ABI. The most straightforward way + // to handle this is to add a "m_grows_downward" bool to the StackID, and set it in the constructor. + // But I'm not going to waste a bool per StackID on this till we need it. + if (lhs_cfa != rhs_cfa) return lhs_cfa < rhs_cfa; diff --git a/lldb/source/Target/ThreadPlan.cpp b/lldb/source/Target/ThreadPlan.cpp index ad45ad2adf8..e47a4b59afe 100644 --- a/lldb/source/Target/ThreadPlan.cpp +++ b/lldb/source/Target/ThreadPlan.cpp @@ -101,7 +101,8 @@ ThreadPlan::ShouldReportStop (Event *event_ptr) { Vote prev_vote = prev_plan->ShouldReportStop (event_ptr); if (log) - log->Printf ("ThreadPlan::ShouldReportStop() returning previous thread plan vote: %s", GetVoteAsCString (prev_vote)); + log->Printf ("ThreadPlan::ShouldReportStop() returning previous thread plan vote: %s", + GetVoteAsCString (prev_vote)); return prev_vote; } } @@ -153,7 +154,8 @@ ThreadPlan::WillResume (StateType resume_state, bool current_plan) addr_t pc = reg_ctx->GetPC(); addr_t sp = reg_ctx->GetSP(); addr_t fp = reg_ctx->GetFP(); - log->Printf("%s Thread #%u: tid = 0x%4.4llx, pc = 0x%8.8llx, sp = 0x%8.8llx, fp = 0x%8.8llx, plan = '%s', state = %s, stop others = %d", + log->Printf("%s Thread #%u: tid = 0x%4.4llx, pc = 0x%8.8llx, sp = 0x%8.8llx, fp = 0x%8.8llx, " + "plan = '%s', state = %s, stop others = %d", __FUNCTION__, m_thread.GetIndexID(), m_thread.GetID(), diff --git a/lldb/source/Target/ThreadPlanStepInRange.cpp b/lldb/source/Target/ThreadPlanStepInRange.cpp index 094a7dc418e..9fc3ad6360a 100644 --- a/lldb/source/Target/ThreadPlanStepInRange.cpp +++ b/lldb/source/Target/ThreadPlanStepInRange.cpp @@ -130,7 +130,9 @@ ThreadPlanStepInRange::ShouldStop (Event *event_ptr) else stop_others = false; - if (FrameIsOlder()) + FrameComparison frame_order = CompareCurrentFrameToStartFrame(); + + if (frame_order == eFrameCompareOlder) { // If we're in an older frame then we should stop. // @@ -146,7 +148,7 @@ ThreadPlanStepInRange::ShouldStop (Event *event_ptr) } } - else if (!FrameIsYounger() && InSymbol()) + else if (frame_order != eFrameCompareYounger && 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 @@ -174,13 +176,13 @@ ThreadPlanStepInRange::ShouldStop (Event *event_ptr) // If not, give the "should_stop" callback a chance to push a plan to get us out of here. // But only do that if we actually have stepped in. - if (!new_plan && FrameIsYounger()) + if (!new_plan && frame_order == eFrameCompareYounger) new_plan = InvokeShouldStopHereCallback(); // If we've stepped in and we are going to stop here, check to see if we were asked to // run past the prologue, and if so do that. - if (new_plan == NULL && FrameIsYounger() && m_step_past_prologue) + if (new_plan == NULL && frame_order == eFrameCompareYounger && m_step_past_prologue) { lldb::StackFrameSP curr_frame = m_thread.GetStackFrameAtIndex(0); if (curr_frame) diff --git a/lldb/source/Target/ThreadPlanStepOut.cpp b/lldb/source/Target/ThreadPlanStepOut.cpp index e8aac1f6ea4..1b2f751f182 100644 --- a/lldb/source/Target/ThreadPlanStepOut.cpp +++ b/lldb/source/Target/ThreadPlanStepOut.cpp @@ -30,7 +30,6 @@ using namespace lldb_private; //---------------------------------------------------------------------- // ThreadPlanStepOut: Step out of the current frame //---------------------------------------------------------------------- - ThreadPlanStepOut::ThreadPlanStepOut ( Thread &thread, @@ -58,7 +57,10 @@ ThreadPlanStepOut::ThreadPlanStepOut StackFrameSP return_frame_sp (m_thread.GetStackFrameAtIndex(frame_idx + 1)); StackFrameSP immediate_return_from_sp (m_thread.GetStackFrameAtIndex (frame_idx)); - m_stack_depth = m_thread.GetStackFrameCount() - frame_idx; + 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 @@ -69,7 +71,13 @@ ThreadPlanStepOut::ThreadPlanStepOut { // 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.reset (new ThreadPlanStepOut(m_thread, + NULL, + false, + stop_others, + eVoteNoOpinion, + eVoteNoOpinion, + frame_idx - 1)); m_step_out_plan_sp->SetOkayToDiscard(true); } else @@ -127,14 +135,13 @@ ThreadPlanStepOut::GetDescription (Stream *s, lldb::DescriptionLevel level) else { if (m_step_out_plan_sp) - s->Printf ("Stepping out to inlined frame at depth: %d so we can walk through it.", m_stack_depth); + 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 at depth: %d using breakpoint site %d", + 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_stack_depth, m_return_bp_id); } } @@ -194,8 +201,27 @@ ThreadPlanStepOut::PlanExplainsStop () BreakpointSiteSP site_sp (m_thread.GetProcess()->GetBreakpointSiteList().FindByID (stop_info_sp->GetValue())); if (site_sp && site_sp->IsBreakpointAtThisSite (m_return_bp_id)) { - const uint32_t num_frames = m_thread.GetStackFrameCount(); - if (m_stack_depth > num_frames) + 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(); @@ -228,10 +254,17 @@ bool ThreadPlanStepOut::ShouldStop (Event *event_ptr) { if (IsPlanComplete()) - { return true; - } - else if (m_stack_depth > m_thread.GetStackFrameCount()) + + 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(); diff --git a/lldb/source/Target/ThreadPlanStepOverRange.cpp b/lldb/source/Target/ThreadPlanStepOverRange.cpp index 9687c65785b..8b4907f863f 100644 --- a/lldb/source/Target/ThreadPlanStepOverRange.cpp +++ b/lldb/source/Target/ThreadPlanStepOverRange.cpp @@ -114,8 +114,10 @@ ThreadPlanStepOverRange::ShouldStop (Event *event_ptr) stop_others = false; ThreadPlan* new_plan = NULL; - - if (FrameIsOlder()) + + FrameComparison frame_order = CompareCurrentFrameToStartFrame(); + + if (frame_order == eFrameCompareOlder) { // If we're in an older frame then we should stop. // @@ -129,15 +131,32 @@ ThreadPlanStepOverRange::ShouldStop (Event *event_ptr) if (new_plan != NULL && log) log->Printf("Thought I stepped out, but in fact arrived at a trampoline."); } - else if (FrameIsYounger()) + else if (frame_order == eFrameCompareYounger) { - new_plan = m_thread.QueueThreadPlanForStepOut (false, - NULL, - true, - stop_others, - eVoteNo, - eVoteNoOpinion, - 0); + // Make sure we really are in a new frame. Do that by unwinding and seeing if the + // start function really is our start function... + StackFrameSP older_frame_sp = m_thread.GetStackFrameAtIndex(1); + + // But if we can't even unwind one frame we should just get out of here & stop... + if (older_frame_sp) + { + const SymbolContext &older_context = older_frame_sp->GetSymbolContext(eSymbolContextEverything); + if (older_context == m_addr_context) + { + new_plan = m_thread.QueueThreadPlanForStepOut (false, + NULL, + true, + stop_others, + eVoteNo, + eVoteNoOpinion, + 0); + } + else + { + new_plan = m_thread.QueueThreadPlanForStepThrough (false, stop_others); + + } + } } else if (!InSymbol()) { diff --git a/lldb/source/Target/ThreadPlanStepRange.cpp b/lldb/source/Target/ThreadPlanStepRange.cpp index 01803a169c1..e67cf28d17a 100644 --- a/lldb/source/Target/ThreadPlanStepRange.cpp +++ b/lldb/source/Target/ThreadPlanStepRange.cpp @@ -43,13 +43,11 @@ ThreadPlanStepRange::ThreadPlanStepRange (ThreadPlanKind kind, m_addr_context (addr_context), m_address_ranges (), m_stop_others (stop_others), - m_stack_depth (0), m_stack_id (), m_no_more_plans (false), m_first_run_event (true) { AddRange(range); - m_stack_depth = m_thread.GetStackFrameCount(); m_stack_id = m_thread.GetStackFrameAtIndex(0)->GetStackID(); } @@ -199,58 +197,26 @@ ThreadPlanStepRange::InSymbol() // Ideally we should remember the whole stack frame list, and then compare that // to the current list. -bool -ThreadPlanStepRange::FrameIsYounger () +lldb::FrameComparison +ThreadPlanStepRange::CompareCurrentFrameToStartFrame() { - LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); + FrameComparison frame_order; - // FIXME: Might be better to do this by storing the FrameID we started in and seeing if that is still above - // us on the stack. Counting the whole stack could be expensive. + StackID cur_frame_id = m_thread.GetStackFrameAtIndex(0)->GetStackID(); - uint32_t current_depth = m_thread.GetStackFrameCount(); - if (current_depth == m_stack_depth) - { - if (log) - log->Printf ("Step range FrameIsYounger still in start function."); - return false; - } - else if (current_depth < m_stack_depth) - { - if (log) - log->Printf ("Step range FrameIsYounger stepped out: start depth: %d current depth %d.", m_stack_depth, current_depth); - return false; - } - else - { - if (log) - log->Printf ("Step range FrameIsYounger stepped in: start depth: %d current depth %d.", m_stack_depth, current_depth); - return true; - } -} - -bool -ThreadPlanStepRange::FrameIsOlder () -{ - LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); - uint32_t current_depth = m_thread.GetStackFrameCount(); - if (current_depth == m_stack_depth) + if (cur_frame_id == m_stack_id) { - if (log) - log->Printf ("Step range FrameIsOlder still in start function."); - return false; + frame_order = eFrameCompareEqual; } - else if (current_depth < m_stack_depth) + else if (cur_frame_id < m_stack_id) { - if (log) - log->Printf ("Step range FrameIsOlder stepped out: start depth: %d current depth %d.", m_stack_depth, current_depth); - return true; + frame_order = eFrameCompareYounger; } else { - if (log) - log->Printf ("Step range FrameIsOlder stepped in: start depth: %d current depth %d.", m_stack_depth, current_depth); - return false; + frame_order = eFrameCompareOlder; } + return frame_order; } bool @@ -285,15 +251,19 @@ ThreadPlanStepRange::MischiefManaged () { done = false; } - else if (!FrameIsOlder()) + else { - if (m_no_more_plans) - done = true; + FrameComparison frame_order = CompareCurrentFrameToStartFrame(); + if (frame_order != eFrameCompareOlder) + { + if (m_no_more_plans) + done = true; + else + done = false; + } else - done = false; + done = true; } - else - done = true; } if (done) diff --git a/lldb/source/Target/ThreadPlanStepUntil.cpp b/lldb/source/Target/ThreadPlanStepUntil.cpp index 1d5f4330754..79c2544dfff 100644 --- a/lldb/source/Target/ThreadPlanStepUntil.cpp +++ b/lldb/source/Target/ThreadPlanStepUntil.cpp @@ -41,15 +41,14 @@ ThreadPlanStepUntil::ThreadPlanStepUntil uint32_t frame_idx ) : ThreadPlan (ThreadPlan::eKindStepUntil, "Step until", thread, eVoteNoOpinion, eVoteNoOpinion), - m_stack_depth (0), m_step_from_insn (LLDB_INVALID_ADDRESS), - m_return_bp_id(LLDB_INVALID_BREAK_ID), + m_return_bp_id (LLDB_INVALID_BREAK_ID), m_return_addr (LLDB_INVALID_ADDRESS), - m_stepped_out(false), - m_should_stop(false), + m_stepped_out (false), + m_should_stop (false), m_ran_analyze (false), - m_explains_stop(false), - m_until_points(), + m_explains_stop (false), + m_until_points (), m_stop_others (stop_others) { @@ -79,7 +78,7 @@ ThreadPlanStepUntil::ThreadPlanStepUntil } } - m_stack_depth = m_thread.GetStackFrameCount() - frame_idx; + m_stack_id = m_thread.GetStackFrameAtIndex(frame_idx)->GetStackID(); // Now set breakpoints on all our return addresses: for (int i = 0; i < num_addresses; i++) @@ -207,7 +206,15 @@ ThreadPlanStepUntil::AnalyzeStop() // If there was another breakpoint here, then we don't explain the stop, but we won't // mark ourselves Completed, because maybe that breakpoint will continue, and then // we'll finish the "until". - if (m_stack_depth > m_thread.GetStackFrameCount()) + bool done; + StackID cur_frame_zero_id; + + if (m_stack_id < cur_frame_zero_id) + done = true; + else + done = false; + + if (done) { m_stepped_out = true; SetPlanComplete(); @@ -230,7 +237,36 @@ ThreadPlanStepUntil::AnalyzeStop() if (this_site->IsBreakpointAtThisSite ((*pos).second)) { // If we're at the right stack depth, then we're done. - if (m_stack_depth == m_thread.GetStackFrameCount()) + + bool done; + StackID frame_zero_id = m_thread.GetStackFrameAtIndex(0)->GetStackID(); + + if (frame_zero_id == m_stack_id) + done = true; + else if (frame_zero_id < m_stack_id) + done = false; + else + { + StackFrameSP older_frame_sp = m_thread.GetStackFrameAtIndex(1); + + // But if we can't even unwind one frame we should just get out of here & stop... + if (older_frame_sp) + { + const SymbolContext &older_context + = older_frame_sp->GetSymbolContext(eSymbolContextEverything); + SymbolContext stack_context; + m_stack_id.GetSymbolContextScope()->CalculateSymbolContext(&stack_context); + + if (older_context == stack_context) + done = true; + else + done = false; + } + else + done = false; + } + + if (done) SetPlanComplete(); else m_should_stop = false; |