Index: lldb/include/lldb/Target/StackID.h =================================================================== --- lldb/include/lldb/Target/StackID.h +++ lldb/include/lldb/Target/StackID.h @@ -62,6 +62,8 @@ return *this; } +lldb::FrameComparison CompareTo(const StackID &rhs) const; + protected: friend class StackFrame; @@ -93,9 +95,6 @@ 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 #endif // LLDB_TARGET_STACKID_H Index: lldb/include/lldb/Target/ThreadPlanStepOut.h =================================================================== --- lldb/include/lldb/Target/ThreadPlanStepOut.h +++ lldb/include/lldb/Target/ThreadPlanStepOut.h @@ -86,6 +86,8 @@ void CalculateReturnValue(); + bool DoesCurrentFrameExplainStop(); + ThreadPlanStepOut(const ThreadPlanStepOut &) = delete; const ThreadPlanStepOut &operator=(const ThreadPlanStepOut &) = delete; }; Index: lldb/source/Target/StackFrameList.cpp =================================================================== --- lldb/source/Target/StackFrameList.cpp +++ lldb/source/Target/StackFrameList.cpp @@ -730,7 +730,7 @@ static bool CompareStackID(const StackFrameSP &stack_sp, const StackID &stack_id) { - return stack_sp->GetStackID() < stack_id; + return stack_sp->GetStackID().CompareTo(stack_id) == eFrameCompareYounger; } StackFrameSP StackFrameList::GetFrameWithStackID(const StackID &stack_id) { Index: lldb/source/Target/StackID.cpp =================================================================== --- lldb/source/Target/StackID.cpp +++ lldb/source/Target/StackID.cpp @@ -30,35 +30,10 @@ s->PutCString(") "); } -bool lldb_private::operator==(const StackID &lhs, const StackID &rhs) { - if (lhs.GetCallFrameAddress() != rhs.GetCallFrameAddress()) - return false; - - SymbolContextScope *lhs_scope = lhs.GetSymbolContextScope(); - SymbolContextScope *rhs_scope = rhs.GetSymbolContextScope(); - - // Only compare the PC values if both symbol context scopes are nullptr - if (lhs_scope == nullptr && rhs_scope == nullptr) - return lhs.GetPC() == rhs.GetPC(); - - return lhs_scope == rhs_scope; -} - -bool lldb_private::operator!=(const StackID &lhs, const StackID &rhs) { - if (lhs.GetCallFrameAddress() != rhs.GetCallFrameAddress()) - return true; - - SymbolContextScope *lhs_scope = lhs.GetSymbolContextScope(); - SymbolContextScope *rhs_scope = rhs.GetSymbolContextScope(); - - if (lhs_scope == nullptr && rhs_scope == nullptr) - return lhs.GetPC() != rhs.GetPC(); +lldb::FrameComparison StackID::CompareTo(const StackID &rhs) const { + if (*this == rhs) + return lldb::eFrameCompareEqual; - return lhs_scope != rhs_scope; -} - -bool 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 @@ -70,28 +45,60 @@ // 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; + if (m_cfa != rhs_cfa) + return m_cfa < rhs_cfa ? lldb::eFrameCompareYounger + : lldb::eFrameCompareOlder; - SymbolContextScope *lhs_scope = lhs.GetSymbolContextScope(); SymbolContextScope *rhs_scope = rhs.GetSymbolContextScope(); - if (lhs_scope != nullptr && rhs_scope != nullptr) { - // Same exact scope, lhs is not less than (younger than rhs) - if (lhs_scope == rhs_scope) - return false; + if (m_symbol_scope != nullptr && rhs_scope != nullptr) { + // Same CFA and same exact scope, StackIDs are equal. + if (m_symbol_scope == rhs_scope) + return lldb::eFrameCompareEqual; SymbolContext lhs_sc; SymbolContext rhs_sc; - lhs_scope->CalculateSymbolContext(&lhs_sc); + m_symbol_scope->CalculateSymbolContext(&lhs_sc); rhs_scope->CalculateSymbolContext(&rhs_sc); // Items with the same function can only be compared if (lhs_sc.function == rhs_sc.function && lhs_sc.function != nullptr && lhs_sc.block != nullptr && rhs_sc.function != nullptr && rhs_sc.block != nullptr) { - return rhs_sc.block->Contains(lhs_sc.block); + if (rhs_sc.block->Contains(lhs_sc.block)) + return lldb::eFrameCompareYounger; + + if (lhs_sc.block->Contains(rhs_sc.block)) + return lldb::eFrameCompareOlder; } } - return false; + + return lldb::eFrameCompareUnknown; +} + +bool lldb_private::operator==(const StackID &lhs, const StackID &rhs) { + if (lhs.GetCallFrameAddress() != rhs.GetCallFrameAddress()) + return false; + + SymbolContextScope *lhs_scope = lhs.GetSymbolContextScope(); + SymbolContextScope *rhs_scope = rhs.GetSymbolContextScope(); + + // Only compare the PC values if both symbol context scopes are nullptr + if (lhs_scope == nullptr && rhs_scope == nullptr) + return lhs.GetPC() == rhs.GetPC(); + + return lhs_scope == rhs_scope; +} + +bool lldb_private::operator!=(const StackID &lhs, const StackID &rhs) { + if (lhs.GetCallFrameAddress() != rhs.GetCallFrameAddress()) + return true; + + SymbolContextScope *lhs_scope = lhs.GetSymbolContextScope(); + SymbolContextScope *rhs_scope = rhs.GetSymbolContextScope(); + + if (lhs_scope == nullptr && rhs_scope == nullptr) + return lhs.GetPC() != rhs.GetPC(); + + return lhs_scope != rhs_scope; } Index: lldb/source/Target/ThreadPlanStepInstruction.cpp =================================================================== --- lldb/source/Target/ThreadPlanStepInstruction.cpp +++ lldb/source/Target/ThreadPlanStepInstruction.cpp @@ -99,7 +99,9 @@ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); Thread &thread = GetThread(); StackID cur_frame_id = thread.GetStackFrameAtIndex(0)->GetStackID(); - if (cur_frame_id == m_stack_id) { + FrameComparison frame_order = cur_frame_id.CompareTo(m_stack_id); + + if (frame_order == eFrameCompareEqual) { // Set plan Complete when we reach next instruction uint64_t pc = thread.GetRegisterContext()->GetPC(0); uint32_t max_opcode_size = @@ -109,19 +111,26 @@ if (next_instruction_reached) { SetPlanComplete(); } - return (thread.GetRegisterContext()->GetPC(0) != m_instruction_addr); - } else if (cur_frame_id < m_stack_id) { + return (pc != m_instruction_addr); + } else if (frame_order == eFrameCompareYounger) { // If the current frame is younger than the start frame and we are stepping // over, then we need to continue, but if we are doing just one step, we're // done. return !m_step_over; - } else { + } else if (frame_order == eFrameCompareOlder) { if (log) { LLDB_LOGF(log, "ThreadPlanStepInstruction::IsPlanStale - Current frame is " "older than start frame, plan is stale."); } return true; + } else { + if (log) + LLDB_LOGF(log, + "ThreadPlanStepInstruction::IsPlanStale - Failed to compare " + "current frame to the start frame, rely on PC comparison."); + + return (thread.GetRegisterContext()->GetPC(0) != m_instruction_addr); } } @@ -140,7 +149,9 @@ StackID cur_frame_zero_id = cur_frame_sp->GetStackID(); - if (cur_frame_zero_id == m_stack_id || m_stack_id < cur_frame_zero_id) { + FrameComparison frame_order = m_stack_id.CompareTo(cur_frame_zero_id); + + if (frame_order == eFrameCompareEqual || frame_order == eFrameCompareYounger) { if (thread.GetRegisterContext()->GetPC(0) != m_instruction_addr) { if (--m_iteration_count <= 0) { SetPlanComplete(); @@ -153,7 +164,7 @@ } } else return false; - } else { + } else if (frame_order == eFrameCompareOlder) { // We've stepped in, step back out again: StackFrame *return_frame = thread.GetStackFrameAtIndex(1).get(); if (return_frame) { @@ -216,6 +227,10 @@ SetPlanComplete(); return true; } + } else { + LLDB_LOGF(log, "Could not compare frame IDs, stopping."); + SetPlanComplete(); + return true; } } else { lldb::addr_t pc_addr = thread.GetRegisterContext()->GetPC(0); Index: lldb/source/Target/ThreadPlanStepOut.cpp =================================================================== --- lldb/source/Target/ThreadPlanStepOut.cpp +++ lldb/source/Target/ThreadPlanStepOut.cpp @@ -293,22 +293,7 @@ BreakpointSiteSP site_sp( m_process.GetBreakpointSiteList().FindByID(stop_info_sp->GetValue())); if (site_sp && site_sp->IsBreakpointAtThisSite(m_return_bp_id)) { - bool done; - - StackID frame_zero_id = - GetThread().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 { - done = (m_immediate_step_from_id < frame_zero_id); - } - - if (done) { + if (DoesCurrentFrameExplainStop()) { if (InvokeShouldStopHereCallback(eFrameCompareOlder, m_status)) { CalculateReturnValue(); SetPlanComplete(); @@ -362,10 +347,8 @@ return m_step_out_further_plan_sp->ShouldStop(event_ptr); } - if (!done) { - StackID frame_zero_id = GetThread().GetStackFrameAtIndex(0)->GetStackID(); - done = !(frame_zero_id < m_step_out_to_id); - } + if (!done) + done = DoesCurrentFrameExplainStop(); // The normal step out computations think we are done, so all we need to do // is consult the ShouldStopHere, and we are done. @@ -524,5 +507,26 @@ // then there's something for us to do. Otherwise, we're stale. StackID frame_zero_id = GetThread().GetStackFrameAtIndex(0)->GetStackID(); - return !(frame_zero_id < m_step_out_to_id); + return frame_zero_id.CompareTo(m_step_out_to_id) != eFrameCompareYounger; +} + +bool ThreadPlanStepOut::DoesCurrentFrameExplainStop() { + StackID frame_zero_id = GetThread().GetStackFrameAtIndex(0)->GetStackID(); + + auto comparison_result = m_step_out_to_id.CompareTo(frame_zero_id); + + if (comparison_result == eFrameCompareYounger || + comparison_result == eFrameCompareEqual) + return true; + + if (comparison_result == eFrameCompareOlder) + return false; + + // We can reach this point if frame_zero_id and m_step_out_to_id have the same + // CFA but belong to different functions. + + if (m_immediate_step_from_id.CompareTo(frame_zero_id) == eFrameCompareYounger) + return true; + + return m_return_addr == frame_zero_id.GetPC(); } Index: lldb/source/Target/ThreadPlanStepRange.cpp =================================================================== --- lldb/source/Target/ThreadPlanStepRange.cpp +++ lldb/source/Target/ThreadPlanStepRange.cpp @@ -213,25 +213,21 @@ // to the current list. lldb::FrameComparison ThreadPlanStepRange::CompareCurrentFrameToStartFrame() { - FrameComparison frame_order; Thread &thread = GetThread(); StackID cur_frame_id = thread.GetStackFrameAtIndex(0)->GetStackID(); - if (cur_frame_id == m_stack_id) { - frame_order = eFrameCompareEqual; - } else if (cur_frame_id < m_stack_id) { - frame_order = eFrameCompareYounger; - } else { - StackFrameSP cur_parent_frame = thread.GetStackFrameAtIndex(1); - StackID cur_parent_id; - if (cur_parent_frame) - cur_parent_id = cur_parent_frame->GetStackID(); + auto frame_order = cur_frame_id.CompareTo(m_stack_id); + if (frame_order != eFrameCompareUnknown) + return frame_order; + + StackFrameSP cur_parent_frame = thread.GetStackFrameAtIndex(1); + if (cur_parent_frame) { + StackID cur_parent_id = cur_parent_frame->GetStackID(); if (m_parent_stack_id.IsValid() && cur_parent_id.IsValid() && m_parent_stack_id == cur_parent_id) frame_order = eFrameCompareSameParent; - else - frame_order = eFrameCompareOlder; } + return frame_order; } Index: lldb/source/Target/ThreadPlanStepUntil.cpp =================================================================== --- lldb/source/Target/ThreadPlanStepUntil.cpp +++ lldb/source/Target/ThreadPlanStepUntil.cpp @@ -173,7 +173,7 @@ bool done; StackID cur_frame_zero_id; - done = (m_stack_id < cur_frame_zero_id); + done = m_stack_id.CompareTo(cur_frame_zero_id) == eFrameCompareYounger; if (done) { m_stepped_out = true; @@ -197,11 +197,13 @@ StackID frame_zero_id = thread.GetStackFrameAtIndex(0)->GetStackID(); - if (frame_zero_id == m_stack_id) + auto frame_compare = frame_zero_id.CompareTo(m_stack_id); + + if (frame_compare == eFrameCompareEqual) done = true; - else if (frame_zero_id < m_stack_id) + else if (frame_compare == eFrameCompareYounger) done = false; - else { + else if (frame_compare == eFrameCompareOlder) { StackFrameSP older_frame_sp = thread.GetStackFrameAtIndex(1); // But if we can't even unwind one frame we should just get out @@ -216,7 +218,8 @@ done = (older_context == stack_context); } else done = false; - } + } else + done = thread.GetRegisterContext()->GetPC(0) == m_return_addr; if (done) SetPlanComplete();