diff options
author | Abhishek Aggarwal <abhishek.a.aggarwal@intel.com> | 2015-11-13 10:47:49 +0000 |
---|---|---|
committer | Abhishek Aggarwal <abhishek.a.aggarwal@intel.com> | 2015-11-13 10:47:49 +0000 |
commit | be994649b44300e53c5c6801dbc5803e67d8ac12 (patch) | |
tree | 8106eaeb2b517b646532cd09a6ffec133345bde2 /lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp | |
parent | a085297030340838f8c5d7e785e4e173b83658ec (diff) | |
download | bcm5719-llvm-be994649b44300e53c5c6801dbc5803e67d8ac12.tar.gz bcm5719-llvm-be994649b44300e53c5c6801dbc5803e67d8ac12.zip |
Fix to solve Bug 23139 & Bug 23560
Summary:
- Reason of both bugs:
1. For the very first frame, Unwinder doesn't check the validity
of Full UnwindPlan before creating StackFrame from it:
When 'process launch' command is run after setting a breakpoint
in inferior, the Unwinder runs and saves only Frame 0 (the frame
in which breakpoint was set) in thread's StackFrameList i.e.
m_curr_frames_sp. However, it doesn't check the validity of the
Full UnwindPlan for this frame by unwinding 2 more frames further.
2. Unwinder doesn't update the CFA value of Cursor when Full UnwindPlan
fails and FallBack UnwindPlan succeeds in providing valid CFA values
for frames:
Sometimes during unwinding of stack frames, the Full UnwindPlan
inside the RegisterContextLLDB object may fail to provide valid
CFA values for these frames. Then the Fallback UnwindPlan is used
to unwind the frames.
If the Fallback UnwindPlan succeeds, then it provides a valid new
CFA value. The RegisterContextLLDB::m_cfa field of Cursor object
is updated during the Fallback UnwindPlan execution. However,
UnwindLLDB misses the implementation to update the 'cfa' field
of this Cursor with this valid new CFA value.
- This patch fixes both these issues.
- Remove XFAIL in test files corresponding to these 2 Bugs
Change-Id: I932ea407545ceee2d628f946ecc61a4806d4cc86
Signed-off-by: Abhishek Aggarwal <abhishek.a.aggarwal@intel.com>
Reviewers: jingham, lldb-commits, jasonmolenda
Subscribers: lldb-commits, ovyalov, tberghammer
Differential Revision: http://reviews.llvm.org/D14226
llvm-svn: 253026
Diffstat (limited to 'lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp')
-rw-r--r-- | lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp | 86 |
1 files changed, 85 insertions, 1 deletions
diff --git a/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp b/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp index 1cdae901167..9be09c478a0 100644 --- a/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp +++ b/lldb/source/Plugins/Process/Utility/UnwindLLDB.cpp @@ -86,6 +86,9 @@ UnwindLLDB::AddFirstFrame () if (m_frames.size() > 0) return true; + ProcessSP process_sp (m_thread.GetProcess()); + ABI *abi = process_sp ? process_sp->GetABI().get() : NULL; + // First, set up the 0th (initial) frame CursorSP first_cursor_sp(new Cursor ()); RegisterContextLLDBSP reg_ctx_sp (new RegisterContextLLDB (m_thread, @@ -108,6 +111,10 @@ UnwindLLDB::AddFirstFrame () // cursor own it in its shared pointer first_cursor_sp->reg_ctx_lldb_sp = reg_ctx_sp; m_frames.push_back (first_cursor_sp); + + // Update the Full Unwind Plan for this frame if not valid + UpdateUnwindPlanForFirstFrameIfInvalid(abi); + return true; unwind_done: @@ -161,7 +168,14 @@ UnwindLLDB::GetOneMoreFrame (ABI* abi) // If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return // true. Subsequent calls to TryFallbackUnwindPlan() will return false. if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) + { + // TryFallbackUnwindPlan for prev_frame succeeded and updated reg_ctx_lldb_sp field of + // prev_frame. However, cfa field of prev_frame still needs to be updated. Hence updating it. + if ( !(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa))) + return nullptr; + return GetOneMoreFrame (abi); + } if (log) log->Printf ("%*sFrame %d did not get a RegisterContext, stopping.", @@ -175,7 +189,14 @@ UnwindLLDB::GetOneMoreFrame (ABI* abi) // See if the regctx below this on the stack has a fallback unwind plan it can use. // Subsequent calls to TryFallbackUnwindPlan() will return false. if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) + { + // TryFallbackUnwindPlan for prev_frame succeeded and updated reg_ctx_lldb_sp field of + // prev_frame. However, cfa field of prev_frame still needs to be updated. Hence updating it. + if ( !(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa))) + return nullptr; + return GetOneMoreFrame (abi); + } if (log) log->Printf("%*sFrame %d invalid RegisterContext for this frame, stopping stack walk", @@ -187,7 +208,14 @@ UnwindLLDB::GetOneMoreFrame (ABI* abi) // If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return // true. Subsequent calls to TryFallbackUnwindPlan() will return false. if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) + { + // TryFallbackUnwindPlan for prev_frame succeeded and updated reg_ctx_lldb_sp field of + // prev_frame. However, cfa field of prev_frame still needs to be updated. Hence updating it. + if ( !(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa))) + return nullptr; + return GetOneMoreFrame (abi); + } if (log) log->Printf("%*sFrame %d did not get CFA for this frame, stopping stack walk", @@ -212,7 +240,14 @@ UnwindLLDB::GetOneMoreFrame (ABI* abi) || abi->CallFrameAddressIsValid(cursor_sp->cfa) == false) { if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) + { + // TryFallbackUnwindPlan for prev_frame succeeded and updated reg_ctx_lldb_sp field of + // prev_frame. However, cfa field of prev_frame still needs to be updated. Hence updating it. + if ( !(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa))) + return nullptr; + return GetOneMoreFrame (abi); + } if (log) log->Printf("%*sFrame %d did not get a valid CFA for this frame, stopping stack walk", @@ -232,7 +267,14 @@ UnwindLLDB::GetOneMoreFrame (ABI* abi) // If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return // true. Subsequent calls to TryFallbackUnwindPlan() will return false. if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) + { + // TryFallbackUnwindPlan for prev_frame succeeded and updated reg_ctx_lldb_sp field of + // prev_frame. However, cfa field of prev_frame still needs to be updated. Hence updating it. + if ( !(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa))) + return nullptr; + return GetOneMoreFrame (abi); + } if (log) log->Printf("%*sFrame %d did not get PC for this frame, stopping stack walk", @@ -244,7 +286,14 @@ UnwindLLDB::GetOneMoreFrame (ABI* abi) // If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return // true. Subsequent calls to TryFallbackUnwindPlan() will return false. if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) + { + // TryFallbackUnwindPlan for prev_frame succeeded and updated reg_ctx_lldb_sp field of + // prev_frame. However, cfa field of prev_frame still needs to be updated. Hence updating it. + if ( !(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa))) + return nullptr; + return GetOneMoreFrame (abi); + } if (log) log->Printf("%*sFrame %d did not get a valid PC, stopping stack walk", @@ -263,6 +312,33 @@ UnwindLLDB::GetOneMoreFrame (ABI* abi) return cursor_sp; } +void +UnwindLLDB::UpdateUnwindPlanForFirstFrameIfInvalid (ABI *abi) +{ + // This function is called for First Frame only. + assert (m_frames.size() == 1 && "No. of cursor frames are not 1"); + + 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); + + // Remove all the frames added by above function as the purpose of + // using above function was just to check whether Unwinder of Frame 0 + // works or not. + for(uint32_t i=1; i<m_frames.size(); i++) + m_frames.pop_back(); + + // Restore status after calling AddOneMoreFrame + m_unwind_complete = old_m_unwind_complete; + m_candidate_frame = old_m_candidate_frame; + return; +} + + bool UnwindLLDB::AddOneMoreFrame (ABI *abi) { @@ -321,9 +397,17 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi) 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; return true; + } - // The new frame isn't helped in unwinding. Fall back to the original one as the default unwind + // 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); |