Add code to RegisterContextLLDB::InitializeNonZerothFrame to detect a multiple stack frames

with the same CFA (or an alternating sequence between two CFA values) to catch a handful of
unwind cases where lldb will inf loop trying to unwind a stack.

llvm-svn: 142331
This commit is contained in:
Jason Molenda 2011-10-18 02:57:27 +00:00
parent f333f8c40d
commit e858e33200
2 changed files with 42 additions and 0 deletions

View File

@ -448,6 +448,38 @@ RegisterContextLLDB::InitializeNonZerothFrame()
return;
}
// If we have a bad stack setup, we can get the same CFA value multiple times -- or even
// more devious, we can actually oscillate between two CFA values. Detect that here and
// break out to avoid a possible infinite loop in lldb trying to unwind the stack.
addr_t next_frame_cfa;
addr_t next_next_frame_cfa = LLDB_INVALID_ADDRESS;
if (m_next_frame.get() && m_next_frame->GetCFA(next_frame_cfa))
{
bool repeating_frames = false;
if (next_frame_cfa == m_cfa)
{
repeating_frames = true;
}
else
{
if (m_next_frame->GetNextFrame() && m_next_frame->GetNextFrame()->GetCFA(next_next_frame_cfa)
&& next_next_frame_cfa == m_cfa)
{
repeating_frames = true;
}
}
if (repeating_frames)
{
if (log)
{
log->Printf("%*sFrame %u same CFA address as next frame, assuming the unwind is looping - stopping",
m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
}
m_frame_type = eNotAValidFrame;
return;
}
}
if (log)
{
log->Printf("%*sFrame %u initialized frame current pc is 0x%llx cfa is 0x%llx",
@ -1219,6 +1251,13 @@ RegisterContextLLDB::GetCFA (addr_t& cfa)
return true;
}
RegisterContextLLDB::SharedPtr
RegisterContextLLDB::GetNextFrame ()
{
return m_next_frame;
}
// Retrieve the address of the start of the function of THIS frame
bool

View File

@ -122,6 +122,9 @@ private:
void
InitializeNonZerothFrame();
SharedPtr
GetNextFrame ();
// Provide a location for where THIS function saved the CALLER's register value
// Or a frame "below" this one saved it, i.e. a function called by this one, preserved a register that this
// function didn't modify/use.