Index: source/Plugins/Process/Utility/RegisterContextLLDB.cpp =================================================================== --- source/Plugins/Process/Utility/RegisterContextLLDB.cpp +++ source/Plugins/Process/Utility/RegisterContextLLDB.cpp @@ -1655,7 +1655,24 @@ m_full_unwind_plan_sp = m_fallback_unwind_plan_sp; - UnwindPlan::RowSP active_row = m_fallback_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset); + // The current offset should be recalculated here. The m_current_offset is + // calculated from the base address of the symbol. The symbol can lie in the PLT + // (Procedure Linkage Table) i.e its a symbol stub for external call. In this case + // the base address for the unwindplan and the base address of the symbol maybe different, hence + // the m_current_offset will be wrong. + + int fallback_offset = m_current_offset; + AddressRange fall_back_unwind_address_range = m_fallback_unwind_plan_sp->GetAddressRange(); + if (fall_back_unwind_address_range.ContainsFileAddress(m_current_pc)) + fallback_offset = m_current_pc.GetOffset() - fall_back_unwind_address_range.GetBaseAddress().GetOffset(); + else + { + UnwindLogMsg ("fallback unwindplan not valid for current pc"); + m_full_unwind_plan_sp = original_full_unwind_plan_sp; + return false; + } + + UnwindPlan::RowSP active_row = m_fallback_unwind_plan_sp->GetRowForFunctionOffset (fallback_offset); if (active_row && active_row->GetCFAValue().GetValueType() != UnwindPlan::Row::CFAValue::unspecified) { Index: source/Plugins/Process/Utility/UnwindLLDB.h =================================================================== --- source/Plugins/Process/Utility/UnwindLLDB.h +++ source/Plugins/Process/Utility/UnwindLLDB.h @@ -149,7 +149,7 @@ GetOneMoreFrame (ABI* abi); bool - AddOneMoreFrame (ABI *abi); + AddMoreFrames (ABI *abi); bool AddFirstFrame (); Index: source/Plugins/Process/Utility/UnwindLLDB.cpp =================================================================== --- source/Plugins/Process/Utility/UnwindLLDB.cpp +++ source/Plugins/Process/Utility/UnwindLLDB.cpp @@ -60,7 +60,7 @@ ProcessSP process_sp (m_thread.GetProcess()); ABI *abi = process_sp ? process_sp->GetABI().get() : NULL; - while (AddOneMoreFrame (abi)) + while (AddMoreFrames (abi)) { #if DEBUG_FRAME_SPEED if ((m_frames.size() % FRAME_COUNT) == 0) @@ -321,10 +321,11 @@ bool old_m_unwind_complete = m_unwind_complete; CursorSP old_m_candidate_frame = m_candidate_frame; - // Try to unwind 2 more frames using the Unwinder. It uses Full UnwindPlan - // and if Full UnwindPlan fails, then uses FallBack UnwindPlan. Also - // update the cfa of Frame 0 (if required). - AddOneMoreFrame(abi); + // Try to unwind as many frames as we can get using the + // Full Unwinder and the Fall back Unwinder and pick the + // one that gives more frames. Also update the cfa of Frame 0 + // with the choosen Unwinder (if required). + AddMoreFrames(abi); // Remove all the frames added by above function as the purpose of // using above function was just to check whether Unwinder of Frame 0 @@ -332,7 +333,7 @@ for(uint32_t i=1; iPrintf ("th%d Unwind of this thread is complete.", m_thread.GetIndexID()); @@ -364,53 +364,60 @@ return false; } - m_frames.push_back(new_frame); - - // If we can get one more frame further then accept that we get back a correct frame. - m_candidate_frame = GetOneMoreFrame(abi); - if (m_candidate_frame) - return true; + int num_frames_pushed = 0; + const int stack_depth_limit = 10; + int m_frames_last_frame_index = m_frames.size() - 1; + + // Here we try to get as many frames as possible (max 10) with the Full Unwinder and + // the Fall Back Unwinder. Which ever Unwinder gives the most frames will be used. + + // First checking with the Full Unwinder. + while (m_candidate_frame && (num_frames_pushed < stack_depth_limit)) + { + m_frames.push_back(m_candidate_frame); + num_frames_pushed++; + m_candidate_frame = GetOneMoreFrame(abi); + } // We can't go further from the frame returned by GetOneMore frame. Lets try to get a // different frame with using the fallback unwind plan. - if (!m_frames[m_frames.size() - 2]->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) + if (!m_frames[m_frames_last_frame_index]->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) { // We don't have a valid fallback unwind plan. Accept the frame as it is. This is a // valid situation when we are at the bottom of the stack. return true; } - // Remove the possibly incorrect frame from the frame list and try to add a different one with - // the newly selected fallback unwind plan. - m_frames.pop_back(); + std::vector popped_frames_save(num_frames_pushed); + + // Now lets try to add frames from the Fallback Unwinder. We save the frames + // obtained from the Full Unwinder, in case we choose to go with it. + popped_frames_save.insert(popped_frames_save.begin(), (m_frames.begin() + m_frames_last_frame_index + 1), m_frames.end()); + m_frames.erase((m_frames.begin() + m_frames_last_frame_index + 1), m_frames.end()); + + int num_frames_pushed_fallback = 0; CursorSP new_frame_v2 = GetOneMoreFrame(abi); - if (new_frame_v2 == nullptr) + + while(new_frame_v2 && (num_frames_pushed_fallback < stack_depth_limit)) { - // We haven't got a new frame from the fallback unwind plan. Accept the frame from the - // original unwind plan. This is a valid situation when we are at the bottom of the stack. - m_frames.push_back(new_frame); - return true; + m_frames.push_back(new_frame_v2); + num_frames_pushed_fallback++; + new_frame_v2 = GetOneMoreFrame(abi); } - // Push the new frame to the list and try to continue from this frame. If we can get a new frame - // then accept it as the correct one. - m_frames.push_back(new_frame_v2); - m_candidate_frame = GetOneMoreFrame(abi); - if (m_candidate_frame) - { - // If control reached here then TryFallbackUnwindPlan had succeeded for Cursor::m_frames[m_frames.size() - 2]. - // It also succeeded to Unwind next 2 frames i.e. m_frames[m_frames.size() - 1] and a frame after that. - // For Cursor::m_frames[m_frames.size() - 2], reg_ctx_lldb_sp field was already updated during TryFallbackUnwindPlan - // call above. However, cfa field still needs to be updated. Hence updating it here and then returning. - if ( !(m_frames[m_frames.size() - 2]->reg_ctx_lldb_sp->GetCFA(m_frames[m_frames.size() - 2]->cfa))) - return false; + if (num_frames_pushed_fallback < num_frames_pushed) + { + m_frames.erase( (m_frames.begin() + m_frames_last_frame_index + 1), m_frames.end()); + m_frames.insert( (m_frames.begin() + m_frames_last_frame_index + 1), popped_frames_save.begin(), popped_frames_save.end()); return true; } - // The new frame hasn't helped in unwinding. Fall back to the original one as the default unwind - // plan is usually more reliable then the fallback one. - m_frames.pop_back(); - m_frames.push_back(new_frame); + if (!m_frames[m_frames_last_frame_index]->reg_ctx_lldb_sp->GetCFA(m_frames[m_frames_last_frame_index]->cfa)) + { + m_unwind_complete = true; + return false; + } + return true; } @@ -426,8 +433,8 @@ ProcessSP process_sp (m_thread.GetProcess()); ABI *abi = process_sp ? process_sp->GetABI().get() : NULL; - while (idx >= m_frames.size() && AddOneMoreFrame (abi)) - ; + if (idx >= m_frames.size()) + AddMoreFrames (abi); if (idx < m_frames.size ()) { @@ -458,11 +465,8 @@ ProcessSP process_sp (m_thread.GetProcess()); ABI *abi = process_sp ? process_sp->GetABI().get() : NULL; - while (idx >= m_frames.size()) - { - if (!AddOneMoreFrame (abi)) - break; - } + if (idx >= m_frames.size()) + AddMoreFrames (abi); const uint32_t num_frames = m_frames.size(); if (idx < num_frames)